TITLE DPY MODULE TO MAKE CRT DISPLAYS EASY SUBTTL DEFINITIONS ;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED ; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ;COPYRIGHT (C) 1976,1977,1978,1979 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. ;THIS MODULE IS USED TO PRODUCE A CONSTANTLY UPDATING DISPLAY. ;COMMUNICATION BETWEEN IT AND THE CALLING PROGRAM IS BY LUUOS. THIS ;MODULE CAN RUN ON VARIOUS KINDS OF TERMINALS. THE FILE DPYDEF.MAC ;CONTAINS ALL OF THE NECESSARY DEFINITIONS. TWOSEG 400000 ;ALWAYS MAKE PROGRAM TWO SEGMENTS SALL ;MAKE GOOD LOOKING MACROS ENTRY DPYUUO ;DEFINE ENTRY POINT INTERN DPYTAB ;AND THE TABLE SEARCH DPYDEF ;GET BIT DEFINITIONS VERSION==3 ;THIRD VERSION OF DPY EDIT==170 ;EDIT NUMBER IFNDEF FTDEC20, ;ON FOR TOPS-20, OFF FOR TOPS-10 DEFINE IF10, ;SHORTHAND CONDITIONALS DEFINE IF20, 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, ;;TERMINAL TYPE NUMBER XX FLAG,> ;;FLAGS XX LEN,,^D23> ;;LENGTH OF SCREEN IFG , ;;REMEMBER NEW MAX VAL2==VAL+1 ;;REMEMBER VALUE XX WID,,^D79> ;;WIDTH OF SCREEN VAL==/4 ;;GET WORDS PER LINE XX WRDS, ;;NUMBER OF WORDS PER LINE IFG , ;;REMEMBER NEW MAX VAL==VAL*VAL2 ;;COMPUTE STORAGE NEEDED IFG , ;REMEMBER NEW MAX XX MAXC, ;;HIGHEST PRINTING CHARACTER XX EATC, ;;CHAR WHICH EATS XX LEFT,SEQ ;;SEQUENCE TO MOVE LEFT XX RHT,SEQ ;;SEQUENCE TO MOVE RIGHT XX UP,SEQ ;;SEQUENCE TO MOVE UP XX DOWN,SEQ ;;SEQUENCE TO MOVE DOWN XX CR,SEQ ;;SEQ TO DO A CARRIAGE RETURN XX HOM,SEQ ;;SEQUENCE TO HOME UP XX CLR,SEQ ;;SEQUENCE TO HOME UP AND CLEAR XX EOL,SEQ ;;SEQUENCE TO ERASE END OF LINE XX EOF,SEQ ;;SEQUENCE TO ERASE END OF FORM XX ADR,SEQ ;;SEQUENCE TO START ADDRESSING XX ADR2,SEQ ;;SEQUENCE FOR FILLS BETWEEN X AND Y XX ADR3,SEQ ;;SEQUENCE FOR FILLS AFTER ADDRESSING XX XOFF, ;;OFFSET FOR X COORDINATE XX YOFF, ;;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 ,< ;;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 ,< ;;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 , ;;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 ,< ;;LOOP OVER ALL CHARS AGAIN WORD==WORD+<_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 ,< ;;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 () ;;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),,, ,,,SP,SP) TTY(ASR33,ASR33,.TT33,25,71,TTY,176,SP,,SP,,LF,CR, ,,,,,,) TTY(ASR35,ASR35,.TT35,25,71,,176,SP,,SP,,LF,CR, ,,,,,,) TTY(VT05,VT05,.TTV05,20,72,,176,SP,CL(H),CL(X), ,,CR,, ,, ,CL(N),,,SP,SP) TTY(VT06,VT06,,25,72,RAI,176,SP,CL(H),CL(X),CL(Z),LF,CR,CL(]), ,CL(^),CL(_),,,,SP,SP) TTY(VT100,VT100,.TT100,24,80,,176,SP,CL(H),, ,LF,CR,,, ,,,,,,) TTY(VT50,VT50,.TTV50,12,80,,176,SP,CL(H),,, LF,CR,,,,,,,,SP,SP) TTY(VT52,VT52,.TTV52,24,80,TAB,176,SP,CL(H),,,LF,CR, ,,,,,,,SP,SP) TTY(VT61,VT61,.TTV61,24,80,TAB,176,SP,CL(H),,,LF,CR, ,,,,,,,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 ,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 OR . 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 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%%==! ;;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 AOJA T2,CHKADF ;COUNT ENDING CHAR AND RETURN 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,-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,() ;FINISH THE INSTRUCTION EXCH T1,TEMP ;RESTORE AC AND STORE INSTRUCTION XCT TEMP ;DO THE I/O POPJ P, ;DONE DIE OPF ;FAILED > SUBTTL ROUTINE TO GIVE CHARS TO USER'S PROGRAM ;HERE WHEN USER WANTS TO GET OUTPUT WE WOULD NORMALLY GIVE TO THE ;TERMINAL. THE USER HAS THE CHOICE OF HAVING HIS ORIGINAL AC'S, OR ;TO BE FASTER, IF FLAG FL.NZP IS SET, WE JUMP DIRECTLY TO ;HIS ROUTINE, ASSUMING HE DOESN'T HURT ANY AC'S. WE GIVE HIM ONE ;CHARACTER AT A TIME. THE USER DOES THE FOLLOWING: ; ; POP P,AC ;BRING THE CHARACTER OFF OF THE STACK ; . ; . ; (THE USER'S RANDOM CODE) ; . ; POPJ P, ;RETURN TO DPY AND CONTINUE AS BEFORE ; ;CALL AT USRLST WHEN ALL OUTPUT FOR THIS UUO IS FINISHED, TO NOTIFY ;THE PROGRAM THAT WE ARE DONE BY SENDING A CHARACTER WITH 1B0 SET. USRLST: MOVSI C,(1B0) ;FLAG THIS AS LAST OUTPUT USROUT: TLNN F,FL.NZP ;DOES USER WANT HIS OWN ACS? JRST USRPAI ;YES, GO DO WORK PUSH P,C ;NO, THEN JUST PUSH THE CHAR PJRST @OUTADR(X) ;AND GO TO USER'S ROUTINE ;HERE IF WE MUST SAVE THE AC'S BEFORE CALLING USER USRPAI: PUSH P,[USRRET] ;PUT THE RETURN ADDRESS ON THE STACK PUSH P,C ;AND PUT THE CHARACTER ON TOO MOVEM F,OURF(X) ;SAVE AN AC OF OURS MOVEI F,@OUTADR(X) ;GET ADDRESS OF ROUTINE TO GO TO MOVEM F,TEMP ;SAVE IT HRLI F,T1 ;SET UP HRRI F,OURT1(X) ;BLT POINTER BLT F,OURBU+1(X) ;SAVE ALL OF OUR AC'S MOVSI U,SAVEF ;NOW GET SET BLT U,U ;RESTORE ALL THE USER'S AC'S JRST @TEMP ;AND GO TO THE USER'S ROUTINE USRRET: MOVEM F,SAVEF ;SAVE A USER'S AC MOVE F,[T1,,SAVET1] ;GET SET BLT F,SAVEU ;SAVE ALL OF USER'S AC'S WE USE MOVE X,@DP+$DPADR ;RESTORE RELOCATION AC MOVSI U,OURF(X) ;GET SET BLT U,U ;RESTORE OUR OWN AC'S POPJ P, ;AND RETURN FROM THIS BIG MESS SUBTTL THE ERROR ROUTINE ;WE GET HERE FROM ONE OF THE DIE CALLS, TO DIE. WE EITHER OUTPUT A ;MESSAGE AND EXIT, OR GO BACK TO THE USER WITH AN ERROR CODE. THE CALL IS: ; ; XCT CODE,DIEBIG ;GO DIE, AND GIVE ERROR CODE IN AC FIELD ; ;THERE IS NO RETURN. IF THE USER TRAPPED THE ERROR, HE CAN DO THE FOLLOWING: ; ; POP P,LOCATION ;RESTORE THE ERROR CODE ; POPJ P, ;RETURN TO LOCATION AFTER DPY ; ;CALL WHICH FAILED DIEBIG: JSP T2,.+1 ;REMEMBER PC SO CAN GET ERROR CODE LDB T2,[POINT 4,-1(T2),12] ;GRAB THE CODE CAILE T2,MAXERR ;IS IT ILLEGAL !!!!???? SETZ T2, ;YES, TAME IT SOMEWHAT SKIPE ERRADR(X) ;DID USER GIVE US A TRAP ADDRESS? JRST TRAP ;YES, GO TO HIM THEN IF10,< OUTSTR [ASCIZ/ ? DPY - /] ;NO, THEN GIVE SOME OF MESSAGE OUTSTR @ERRTAB(T2) ;AND REST EXIT 1, ;THEN EXIT JRST .-1 ;AND STAY THAT WAY > IF20,< HRROI T1,[ASCIZ/ ? DPY - /] ;GET SOME OF MESSAGE PSOUT ;OUTPUT IT HRROI T1,@ERRTAB(T2) ;GET REST OF TEXT PSOUT ;OUTPUT IT TOO HALTF ;QUIT JRST .-1 ;AND STAY THAT WAY > ;HERE TO RETURN TO THE USER WITH THE ERROR CODE TRAP: MOVE P,SAVEP ;RESTORE A POINTER WE KNOW IS GOOD PUSH P,T2 ;SAVE THE ERROR CODE ON IT MOVE T1,ERRADR(X) ;GET ADDRESS WHERE TO TRAP TO MOVEM T1,TEMP ;SAVE IN KNOWN PLACE PUSHJ P,RETURN ;RESTORE THE USER'S AC'S JRST @TEMP ;JUMP BACK TO USER ;HERE ARE THE POSSIBLE ERRORS ERRTAB: ERR UKE,Unknown error ERR ILR,Illegal luuo received ERR USL,Updated same location twice ERR IWS,Illegal window size given ERR ISF,Illegal set function given ERR ITF,Illegal tty function given ERR CDS,Cannot output desired sequence ERR OPF,Output error occurred ERR IPG,Illegal terminal address given ERR ING,Initialize function not given ERR IFF,Initialize function failed MAXERR==.-ERRTAB-1 ;THE MAXIMUM ERROR SUBTTL CONSTANTS AVAILABLE TO USER PROGRAM ;THE FOLLOWING TABLE IS INCLUDED SO THAT THE USER PROGRAM ;CAN READ SOME PARAMETERS WHICH DPY USES. THESE ARE REFERENCED ;BY THEIR OFFSET INTO THE DPYTAB TABLE. DP: ;ALTERNATIVE LABEL DPYTAB: EXP DATBEG+TERSIZ ;(0) POINTER TO TERMINAL LENGTH EXP DATBEG+TERSIZ+1 ;(1) POINTER TO TERMINAL WIDTH EXP DATBEG+MINL ;(2) POINTER TO PRESENT WINDOW SIZE EXP DATBEG+OVFVAL ;(3) POINTER TO CURRENT WINDOW COUNTER EXP DATLEN ;(4) LENGTH OF IMPORTANT DATA EXP DATADR ;(5) POINTER TO ADDRESS OF THE DATA EXP DATBEG+SCREEN ;(6) ADDRESS OF STORAGE FOR SCREEN XWD MAXERR,ERRTAB ;(7) ERROR TABLE -- NOTE NOT RELOCATABLE EXP TTYTYP ;(10) POINTER TO TERMINAL TYPE TABLE EXP DATBEG+TTYJFN ;(11) POINTER TO JFN USING FOR TTY EXP DATBEG+EATNUM ;(12) POINTER TO NUMBER OF LINES TO EAT SUBTTL LOW SEGMENT STORAGE ;FIRST, DUMP OUT ALL THE HIGH-SEG LITERALS XLIST ;LITERALS LIT LIST ;HERE IS THE ACTUAL DATA REQUIRED BY THE PROGRAM. THESE ARE IN THE ;LOW SEGMENT SO THAT THE PROGRAM CAN BE PURE. RELOC 0 ;MOVE TO LOW SEGMENT NOW SAVEF: BLOCK 1 ;STORAGE OF THE USER'S AC'S SAVET1: BLOCK 1 SAVET2: BLOCK 1 SAVET3: BLOCK 1 SAVET4: BLOCK 1 SAVEX: BLOCK 1 SAVEC: BLOCK 1 SAVEA: BLOCK 1 SAVEL: BLOCK 1 SAVEN: BLOCK 1 SAVEB: BLOCK 1 SAVEU: BLOCK 1 ZERO: BLOCK 1 ;CONTAINS ZERO SAVEP: BLOCK 1 ;PUSH-POINTER STORED IN CASE OF ERROR TEMP: BLOCK 1 ;TEMPORARY STORAGE DATADR: BLOCK 1 ;ADDRESS OF THE RELOCATABLE DATA INIFLG: BLOCK 1 ;FLAGS FROM INI$ FUNCTION INICNT: BLOCK 1 ;NUMBER OF ARGUMENTS IN INI$ FUNCTION BEST: BLOCK 1 ;LOWEST NUMBER OF CHARS TO MOVE CURSER TABNUM: BLOCK 1 ;NUMBER OF TABS NEEDED TO MOVE TO RIGHT TABUSE: BLOCK 1 ;TABS NEEDED IN BEST CASE FSTCHG: BLOCK 1 ;FIRST PLACE ON A LINE NEEDING CHANGING LSTCHG: BLOCK 1 ;LAST PLACE ON A LINE TO NEED CHANGING PRECHG: BLOCK 1 ;LAST PLACE TO CHANGE PRECEEDING PRESENT ;LOCATION ON A LINE LSTNON: BLOCK 1 ;THE LOCATION OF THE LAST NON-SPACE ;THE FOLLOWING DATA IS REFERENCED BY INDEXING OFF OF AC X. THUS THE ACTUAL ;ADDRESS OF THE DATA IS VARIABLE, AND CAN BE SET BY THE USER. DEFINE WD(SYM,LEN<1>),< ;;MACRO TO DEFINE OFFSETS SYM:! BLOCK LEN > DATBEG: PHASE 0 ;THIS DATA IS PHASED SINCE INDEXED OFF OF X WD OURF ;STORAGE FOR OUR AC'S WD OURT1 WD OURT2 WD OURT3 WD OURT4 WD OURX WD OURC WD OURA WD OURLN,2 ;STORAGE FOR ACS L AND N WD OURBU,2 ;STORAGE FOR ACS B AND U WD MINL ;LOWEST LINE NUMBER IN CURRENT WINDOW WD MAXL ;HIGHEST LINE NUMBER IN WINDOW WD MINN ;LOWEST COLUMN NUMBER IN WINDOW WD MAXN ;HIGHEST COLUMN NUMBER IN WINDOW WD TTYL ;LINE NUMBER THE TTY CURSER IS AT NOW WD TTYN ;COLUMN NUMBER THE TTY CURSER IS AT NOW WD BUFPTR ;BYTE POINTER INTO TTY BUFFER WD BUFCNT ;NUMBER OF CHARACTERS IN TTY BUFFER WD TTYBUF,TTYLEN ;TTY BUFFER WD TERSIZ,2 ;TERMINAL'S LENGTH AND WIDTH WD TTYJFN ;JFN OR BUFFER,,CHANNEL FOR OUTPUT WD TABS,4 ;BIT TABLE FOR TAB STOPS WD SCREEN,MAXARE ;SCREEN STORAGE ;THE REMAINING LOCATIONS ARE CLEARED ON INITIALIZATION: ZERBLK: WD OUTADR ;ADDRESS OF ROUTINE TO GIVE OUTPUT CHARS TO WD ERRADR ;ADDRESS OF ROUTINE TO GO TO ON FATAL ERRORS WD OVFVAL ;WINDOW MOVING INFORMATION WHEN ONE FILLS UP WD EATNUM ;NUMBER OF LINES TO IGNORE FROM USER WD LINCHG,MAXLEN ;FLAGS TO KNOW IF A LINE HAS BEEN CHANGED ZEREND==.-1 ;LAST LOCATION TO ZERO DATLEN: DEPHASE ;LENGTH OF RELOCATABLE DATA END