.NLIST TTM,BEX .ENABL LC ;RBD01 .TITLE ICE - INTERACTIVE CHARACTER EDITOR .IDENT "V2.1S" ;RBD05 .SBTTL INTRODUCTION ; ; ICE - INTERACTIVE CHARACTER EDITOR ; ; AUTHOR: STANLEY ISREAL GOLDFARB ; DATE: 1-SEP-78 ; ; Modified by: Robert B. Denny ;RBD01 ; 30-Jun-80 Mods for RSX V3.2/FDX TTDRV ;RBD01 ; 11-Jul-80 Bug fix - scan by command name ;RBD02 ; 7-Aug-80 Stripdown for small size and ;RBD03 ; Rearrange/change cmds for VT100 ;RBD03 ; 12-Aug-80 Rearrange command tables to reduce ;RBD04 ; overhead on escape sequences and ;RBD04 ; common commands. Bug fixes. ;RBD04 ; ; 14-Aug-80 Fixed bug preventing editing existing ;RBD05+ ; files with specified version number. ; Tried to open same file for input and ; output ;RBD05- ; ; ASSEMBLY: MAC ICE=ICE ; ; TASK BUILD: TKB ICE=ICE ; ; INSTALL: INS ICE/TASK=...EDI ;RBD03 ; INS ICE/TASK=...MAK ; ; ; ICE IS DESIGNED TO PROVIDE A REASONABLE COMPROMISE BETWEEN ; CHARACTER-ORIENTED EDITORS AND WORD-PROCESSORS, FOR A TIME ; SHARING SYSTEM. ; ;-----------------------------------------------------------------------;RBD03+ ; ICE V2.1S ;RBD05 ; ; This is a moderately stripped down version of ICE. The objective here ; is to create a bare bones task which will run in an 8K partition, ; allowing several users to share a small CPU (i.e. an 11/23) comfortably. ; ; Some features were removed, mostly those that were not used often. ; (For more sophisticated editing tasks, use TECO V36.) ; It runs on RSX-11M V3.2 with the FDX terminal driver and typeahead. ; It does 1 character inputs, using the typeahead buffer if it must. ; No AST's are used at any time. ; ; The commands have been changed (rearranged/deleted), and the VT100 ; keypad is now required. It should be very easy to change the layout ; of the commands fo the VT52. ; ; Robert B. Denny ; 7-Aug-80 ; ;-----------------------------------------------------------------------;RBD03- .SBTTL SYSTEM MACRO CALLS .MCALL FDBDF$ FDAT$A FDRC$A FDOP$A FDBF$A FSRSZ$ .MCALL FINIT$ OPEN$ GET$ PUT$ CLOSE$ DELET$ .MCALL STSE$S QIOW$ GMCR$ DIR$ ALUN$S GTSK$ .MCALL ABRT$ EXIT$S .SBTTL CONSTANTS ; ; BUFFER CONTROL CONSTANTS ; NM.LIN= 80. ;NUMBER LINES IN BUFFER ;RBD04+ NM.SAV= NM.LIN/10. ;NUMBER OF "SAVE" BUFFER LINES NM.FIL= 3*NM.LIN/4 ;NUMBER LINES TO BE FILLED FROM FILE NM.SCR= NM.LIN-NM.FIL ;NUMBER OF LINES TO SCROLL TO FILE NM.CHR= 80. ;NUMBER CHARS CAN FIT IN LINE NM.STL= NM.CHR ;SEARCH/REPLACE TEXT LENGTH ;RBD01- ; ; SCREEN CONTROL CONSTANTS ; SC.LIN= 22. ;BOTTOM LINE ON SCREEN (0 TO 22.) SC.CUR= 14. ;CURSOR LINE POSITION (0 TO 22.) ;RBD01 ; ; LUN NUMBER ASSIGNMENTS ; LN.IFL= 1 ;NORMAL INPUT FILE LN.OFL= 2 ;NORMAL OUTPUT FILE LN.TTY= 3 ;TERMINAL INPUT/OUTPUT ; ; EVENT FLAG ASSIGNMENTS ; EF.NWT= 1 ;NORMAL I/O WAIT EF.FCS= 3 ;FCS I/O WAIT ; ; FLAG BITS FOR "FLAGS" ; FL.RPM= 000001 ;REPLACE MODE IS IN EFFECT FL.MCD= 000002 ;BOTTOM LINE MESSAGE DISPLAYED FL.IFO= 000010 ;INPUT FILE IS OPEN FL.OFO= 000020 ;OUTPUT FILE IS OPEN FL.LCS= 000100 ;LAST COMMAND WAS A "SEARCH" FL.PAG= 000200 ;END OF PAGE IN BUFFER FL.EOF= 100000 ;END OF INPUT FILE DETECTED .SBTTL FILE BLOCKS .PSECT DATA ; ; INPUT FILE FDB ; INPFDB: FDBDF$ FDRC$A FDOP$A LN.IFL,IOFNAM,,FO.RD FDBF$A EF.FCS ; ; OUTPUT FILE FDB ; OUTFDB: FDBDF$ FDAT$A R.VAR,FD.CR FDRC$A FDOP$A LN.OFL,IOFNAM,,FO.WRT!FA.NSP FDBF$A EF.FCS ;RBD01-- ; ; FILE NAME DESCRIPTOR BLOCK ; IOFNAM: .WORD 0,0 ;DEVICE NAME LENGTH, ADDRESS (DV:) .WORD 0,0 ;DIRECTORY LENGTH, ADDRESS ([X,Y]) .WORD 0,0 ;FILE NAME LENGTH, ADDRESS (FIL.EXT) IOFSTR: .ASCII /SY000:[377,377]IOFILENAM.EXT;777777................../ IOFLEN= .-IOFSTR .EVEN ;RBD01-- ; ; DEFAULT DEVICE NAME STRING ; DFDEV: .ASCII /SY0:/ .EVEN ; ; FCS I/O AREA ; FSRSZ$ 2,<2*1000>,DATA ;RBD03 .SBTTL BUFFER SPACE ; ; BUFFER CONTROL WORDS ; BFTOP: .WORD 0 ;POINTS TO TOP LINE BFBOT: .WORD 0 ;POINTS TO BOTTOM LINE BFCUR: .WORD 0 ;POINTS TO CURRENT LINE BFPOS: .WORD 0 ;POSITION IN CURRENT LINE BFALL: .WORD 0 ;NUMBER OF BUFFERS ALLOCATED SVTOP: .WORD 0 ;POINTS TO TOP SAVE BUFFER LINE SVBOT: .WORD 0 ;POINTS TO BOTTOM SAVE BUFFER LINE BFUBP: .WORD .+2 ;POINTS TO FIRST IN LINE BUFFER POOL ; ; LINE BUFFER POOL, EACH LINE BUFFER CONTAINS A FORWARD POINTER TO THE ; NEXT LINE, AND A BACKWARD POINTER TO THE PREVIOUS LINE ; NM.XXX= 0 .REPT NM.LIN+NM.SAV NM.XXX= NM.XXX+1 .IF NE,NM.LIN-NM.XXX .WORD .+6+<&177776> ;FORWARD POINTER TO NEXT LINE .IFF .WORD 0 ;FORWARD POINTER TO NEXT LINE .ENDC .WORD 0 ;BACKWARD POINTER TO PREVIOUS LINE .WORD 0 ;CURRENT NUMBER OF CHARS IN LINE .BLKB &177776 ;CHARACTER IN LINE .ENDR ; ; SEARCH AND REPLACE ARGUMENT BUFFERS ; BFSCH: .WORD 0 ;BYTE COUNT FOR SEARCH TEXT .BLKB &177776 ;SEARCH TEXT BUFFER BFREP: .WORD 0 ;BYTE COUNT FOR REPLACE TEXT .BLKB &177776 ;REPLACE TEXT BUFFER ; ; TEMPORARY BUFFER FOR SAVING DATA DURING INPUT ; BFTMP: .BLKB &177776 ;SAVE TEXT HERE DURING LINE INPUT ; ; CHARACTER INPUT CONTROL ; INLST: .WORD 0 ;LAST CHARACTER PROVIDED AS INPUT .SBTTL DATA ; ; GENERAL DATA ; FLAGS: .WORD 0 ;CONTROL FLAGS REPCT: .WORD 0 ;COMMAND REPEAT COUNTER NMCOL: .WORD 80. ;NUMBER OF COLUMNS DISPLAYABLE ; ; DISPLAY BUFFERS ; DSPCRB: .BLKB 14 ;DISPLAY CHARACTER (DSPCR) DSPPSB: .BYTE 33,'Y,00,00 ;DISPLAY CURSOR POSITION (DSPPS) DSPESB: .BYTE 33,00 ;DISPLAY ESCAPE SEQUENCE (DSPES) DSPLNB: .BYTE 033,131,000,000,033,113 ;DISPLAY LINE OF TEXT (DSPLN) .BLKB 152. .EVEN ; ; MOVE CURSOR UP/DOWN POSITION CONTROL WORDS (CMDMCU/CMDMCD) ; MCLRP: .WORD -1 ;LAST RECORDED POSITION MCORP: .WORD -1 ;ORIGINAL RECORDED POSITION ; ; GENERAL CONTROL DIRECTIVES ; GMCR: GMCR$ ;GET INITIAL MCR COMMAND LINE GTSK: GTSK$ BFUBP+2 ;GET TASK PARAMETERS (FOR ABORT) ABRT: ABRT$ ;ABORT TASK (EMERGENCY EXIT) ; ; COMMON OUTPUT QIO ; QIOW: QIOW$ IO.WAL,LN.TTY,EF.NWT,,,,<0,0> ; ; ATTACH/DETACH USER TERMINAL ; ICEATQ: QIOW$ IO.ATT,LN.TTY,EF.NWT,,ICEATS ;RBD01 ICEATS: .BLKW 2 ; ; DO SINGLE CHARACTER INPUTS USING THE TYPEAHEAD BUFFER ;RBD01 ; INCHRQ: QIOW$ IO.RAL!TF.RNE,LN.TTY,EF.NWT,,INCISB,, ;RBD01+ INCISB: .BLKW 2 ;RBD02 ; ; INPUT LINE FROM USE (USED IN "INLIN") ; INLINQ: QIOW$ IO.RLB,LN.TTY,EF.NWT,,INLINS,,<0,0> INLINS: .BLKW 2 .SBTTL COMMAND INTERPRETATON TABLES .PSECT ICE ; ; COMMAND TABLE ENTRY DEFINITION MACRO ; .MACRO CMDENT CHAR,FLAGS,CMDRTN ;DEFINE TABLE ENTRY .BYTE CHAR,FLAGS ;COMMAND CHARACTER AND FLAGS .WORD CMDRTN ;COMMAND ROUTINE .ENDM ; ; COMMAND TABLE ENTRY FLAGS ; FC.ICB= 001 ;INPUT NEW CHAR BEFORE EXECUTION FC.ICA= 002 ;INPUT NEW CHAR AFTER EXECUTION FC.ICI= 004 ;INPUT NEW CHAR AFTER IF CARRY SET FC.TBL= 010 ;USE CMDRTN AS SECONDARY TBL ADDRESS FC.RET= 020 ;RETURN TO MAIN ROUTINE IF CARRY SET FC.NRP= 040 ;DON'T RESET REPCT AFTER EXECUTION FC.SCH= 100 ;SET FL.LCS FLAG AFTER EXECUTION FC.IDR= 200 ;COMMAND IS ILLEGAL DURING REPLACE MODE ; ; Control Character Definitions ;RBD04+ ; ETX = 003 ; ^C HT = 011 ; Tab LF = 012 ; Line Feed FF = 014 ; Form Feed or CR = 015 ; Carriage Return NAK = 025 ; ^U SUB = 032 ; ^Z ESC = 033 ; Escape DEL = 177 ; Delete ; ; COMMAND TABLE - SINGLE CHARACTER COMMANDS ; CMDTBL: CMDENT ESC,FC.ICB+FC.TBL,CMDTB1;PROCESS UNSHIFTED ESCAPE SEQ. ;RBD04 CMDENT DEL,FC.ICA,CMDDPC ;DELETE PREVIOUS CHARACTER ;RBD04 CMDENT ETX,FC.ICA+FC.RET,CMDKIL;KILL AND EXIT CMDENT CR,FC.ICA,CMDINL ;INSERT NEW LINE AFTER CURRENT CMDENT NAK,FC.ICA,CMDDSL ;DELETE START OF LINE CMDENT SUB,FC.RET,CMDCAE ;CLOSE AND EXIT CMDENT DEL,FC.ICA,CMDDPC ;DELETE PREVIOUS CHARACTER CMDENT -01,FC.ICA,CMDINS ;INSERT ALL OTHER CHARACTERS ; ; COMMAND TABLE - X ; CMDTB1: CMDENT '? ,FC.ICB+FC.TBL,CMDTB2;PROCESS UNSHIFTED AUX KEY CMD ;RBD04+ CMDENT 'A ,FC.ICA,CMDMCU ;MOVE CURSOR UP CMDENT 'B ,FC.ICA,CMDMCD ;MOVE CURSOR DOWN CMDENT 'C ,FC.ICA,CMDMCR ;MOVE CURSOR RIGHT CMDENT 'D ,FC.ICA,CMDMCL ;MOVE CURSOR LEFT CMDENT 'P ,FC.ICA,CMDONL ;OPEN NEW LINE CMDENT 'Q ,FC.ICA,CMDDCC ;DELETE CURRENT CHARACTER CMDENT 'R ,FC.ICA,CMDDCL ;DELETE CURRENT LINE CMDENT 'S ,FC.ICA,CMDGNP ;GET NEXT PAGE ;RBD04- CMDENT '- ,FC.NRP,CMDNRC ;SET NEGATIVE REPEAT COUNT CMDENT '0 ,FC.NRP,CMDPRC ;SET POSITIVE REPEAT COUNT CMDENT '1 ,FC.NRP,CMDPRC ;SET POSITIVE REPEAT COUNT CMDENT '2 ,FC.NRP,CMDPRC ;SET POSITIVE REPEAT COUNT CMDENT '3 ,FC.NRP,CMDPRC ;SET POSITIVE REPEAT COUNT CMDENT '4 ,FC.NRP,CMDPRC ;SET POSITIVE REPEAT COUNT CMDENT '5 ,FC.NRP,CMDPRC ;SET POSITIVE REPEAT COUNT CMDENT '6 ,FC.NRP,CMDPRC ;SET POSITIVE REPEAT COUNT CMDENT '7 ,FC.NRP,CMDPRC ;SET POSITIVE REPEAT COUNT CMDENT '8 ,FC.NRP,CMDPRC ;SET POSITIVE REPEAT COUNT CMDENT '9 ,FC.NRP,CMDPRC ;SET POSITIVE REPEAT COUNT CMDENT -01,FC.NRP,CMDZRC ;SET ZERO REPEAT COUNT ; ; COMMAND TABLE - ?X ; CMDTB2: CMDENT 'q ,FC.ICA,CMDBNL ;BEGINNING OF NEXT LINE ;RBD04 CMDENT 'w ,FC.ICA,CMDBPL ;BEGINNING OF PREV LINE ;RBD04 CMDENT 's ,FC.ICA,CMDENL ;END OF NEXT LINE ;RBD04 CMDENT 'y ,FC.ICA,CMDEPL ;END OF PREVIOUS LINE ;RBD04 CMDENT 'M ,FC.ICI+FC.NRP,CMDIST;INPUT SEARCH TEXT CMDENT 'l ,FC.ICA,CMDSCR ;SCROLL ;RBD04 CMDENT 'm ,FC.ICA,CMDSTO ;WRITE LINE(S) TO OUTPUT FILE ;RBD04 CMDENT 'n ,FC.ICA+FC.SCH,CMDSFT;SEARCH FOR TEXT CMDENT 'p ,FC.ICB+FC.TBL,CMDTB3;PROCESS SHIFT (1) COMMAND CMDENT 'r ,FC.ICA,CMDBOP ;BOTTOM OF PAGE CMDENT 't ,FC.ICA,CMDBOL ;BEGINNING OF LINE CMDENT 'u ,FC.ICA,CMDFRM ;NEXT FRAME CMDENT 'v ,FC.ICA,CMDEOL ;END OF LINE CMDENT 'x ,FC.ICA,CMDTOP ;TOP OF PAGE CMDENT -01,FC.ICA,CMDNOP ;UNKNOWN COMMAND ; ; COMMAND TABLE - X ; CMDTB3: CMDENT ESC,FC.ICB+FC.TBL,CMDTB4;PROCESS SHIFTED ONCE ESC SEQUENCE CMDENT -01,FC.ICA,CMDNOP ;UNRECOGNIZED IS A NO-OP ; ; COMMAND TABLE - X ; CMDTB4: CMDENT '? ,FC.ICB+FC.TBL,CMDTB5;PROCESS SHIFTED ONCE AUX KEY COMMAND CMDENT 'A ,FC.ICA+FC.IDR,CMDANL;APPEND NEXT LINE CMDENT 'B ,FC.ICA+FC.IDR,CMDDAL;DELETE AND APPEND LINE CMDENT 'C ,FC.ICA,CMDDEL ;DELETE END OF LINE CMDENT 'D ,FC.ICA,CMDDSL ;DELETE START OF LINE CMDENT 'P ,FC.ICA+FC.IDR,CMDCSB;CLEAR SAVE BUFFER CMDENT 'Q ,FC.ICA+FC.IDR,CMDISB;INSERT IN SAVE BUFFER CMDENT 'R ,FC.ICA+FC.IDR,CMDPNL;PREFACE NEXT LINE CMDENT -01,FC.NRP,CMDNOP ;UNKNOWN COMMAND ; ; COMMAND TABLE - ?X ; CMDTB5: CMDENT 'M ,FC.ICI+FC.NRP,CMDIRT;INPUT REPLACE TEXT CMDENT 'n ,FC.ICA+FC.IDR,CMDRWT;REPLACE WITH TEXT CMDENT 'p ,FC.ICB+FC.TBL,CMDTB6;PROCESS SHIFT (2) COMMAND CMDENT 'q ,FC.ICA,CMDCLC ;CHANGE TO LOWER CASE CMDENT 'r ,FC.ICA+FC.IDR,CMDCTR;CENTER TEXT ON 40'TH COLUMN CMDENT 's ,FC.ICA,CMDNOP ;CMD -UNDECIDED CMDENT 't ,FC.ICA,CMDCUC ;CHANGE TO UPPER CASE CMDENT 'u ,FC.ICA,CMDICV ;INSERT NEXT CHARACTER VERBATIM CMDENT 'v ,FC.ICA,CMDFNW ;FIND NEXT WORD CMDENT 'w ,FC.ICA+FC.IDR,CMDULN;UNSAVE AND CLEAR LINE FROM SAVE BUFFER CMDENT 'x ,FC.ICA+FC.IDR,CMDUSB;UNSAVE ALL TEXT IN SAVE BUFFER CMDENT -01,FC.ICA,CMDNOP ;UNKNOWN COMMAND ;RBD04-- ; ; COMMAND TABLE - X ; CMDTB6: CMDENT ESC,FC.ICB+FC.TBL,CMDTB7;PROCESS SHIFTED TWICE ESC SEQUENCE CMDENT -01,FC.ICA,CMDNOP ;UNRECOGNIZED IS A NO-OP ; ; COMMAND TABLE - X ; CMDTB7: CMDENT '? ,FC.ICB+FC.TBL,CMDTB8;PROCESS SHIFTED TWICE AUX KEY COMMAND CMDENT 'A ,FC.ICA+FC.IDR,CMDANP;APPEND NEXT PAGE CMDENT 'B ,FC.ICA+FC.IDR,CMDDAP;DELETE END AND APPEND NEXT PAGE CMDENT 'C ,FC.ICA,CMDDEP ;DELETE END OF PAGE CMDENT 'D ,FC.ICA,CMDDBP ;DELETE BEGINNING OF PAGE CMDENT -01,FC.NRP,CMDNOP ;UNKNOWN COMMAND ;RBD04-- ; ; COMMAND TABLE - ?X ; CMDTB8: CMDENT 'M ,FC.ICA,CMDERM ;ENTER REPLACE MODE CMDENT 'n ,FC.ICA,CMDXRM ;EXIT REPLACE MODE CMDENT 'p ,FC.ICA,CMDDSP ;REFRESH SCREEN DISPLAY CMDENT 'q ,FC.RET,CMDCAE ;CLOSE AND EXIT CMDENT 'r ,FC.ICA,CMDCAR ;CLOSE AND REOPEN CMDENT 't ,FC.ICA,CMDEOF ;END OUTPUT FILE ;RBD04-- CMDENT 'u ,FC.ICA,CMDCAO ;CLOSE AND OPEN NEW FILE CMDENT 'w ,FC.ICA,CMDCAE ;CLOSE OUTPUT FILE ;RBD04-- CMDENT 'x ,FC.ICA,CMDCDI ;CLOSE AND DELETE INPUT FILE CMDENT -01,FC.ICA,CMDNOP ;UNKNOWN COMMAND ;RBD04-- .SBTTL COMMAND ROUTINE MESSAGES ; ; THESE MESSAGES ARE USED BY THE COMMAND INTERPRETATION ROUTINES ; .MACRO MGEN MESS .NCHR X, .WORD X .ASCII /MESS/ .EVEN .ENDM MGEN ICEATB: MGEN ICEENB: MGEN ICEEXB: MGEN NBUFB: MGEN NLINB: MGEN ESRTB: MGEN ERPTB: MGEN ESRPB: MGEN ESRFB: MGEN ESBCB: MGEN ESAVB: MGEN EFILB: MGEN EEOFB: MGEN ESCRB: MGEN ESCEB: MGEN ENFNB: MGEN ENSFB: MGEN ECNFB: MGEN ENOFB: MGEN EKILB: MGEN ECDIB: MGEN EENDB: MGEN EERMB: MGEN EIDRB: MGEN EXRMB: MGEN GETERB: MGEN PUTERB: MGEN SCRUPB: .WORD 1,12 .SBTTL ICE - MAIN ENTRY ;+ ; -ICE- MAIN ENTRY POINT FOR EDITOR ; ; NOTE: ; R3 ALWAYS CONTAINS THE CURRENT SCREEN COLUMN POSITION FOR ; THE BUFFER DISPLAY. THE CURRENT SCREEN LINE POSITION IS ; ALWAYS DETERMINED BY THE CONSTANT "SC.CUR". ;- .ENABL LC ;RBD02 VT52: .WORD 5 ;RBD02 .ASCII <33>|[?2l|<0> ;FORCE VT52 MODE IF IN ANSI ;RBD02 ICE:: FINIT$ ;INIT THE FCS ;RBD02 ALUN$S #LN.TTY,#"TI,#0 ;ASSIGN THE TI: LUN DIR$ #ICEATQ ;ATTACH TERMINAL BCS 10$ ;BR IF CANT TSTB $DSW ;DID DIRECTIVE GET THROUGH? BLE 10$ ;BR IF NO TSTB ICEATS ;DID IT WORK? BLE 10$ ;BR IF NO MOV VT52,QIOW+Q.IOPL+2 ;FORCE VT52 MODE MOV #VT52+2,QIOW+Q.IOPL DIR$ #QIOW MOV #'=,R0 ;ENTER ALTERNATE KEYPAD MODE CALL DSPES ;DO IT CALL CLRSC ;CLEAR THE SCREEN MOV #ICEENB,R0 ;POINT AT ENTER MESSAGE CALL DSPMS ;DISPLAY IT CLR R3 ;INITIALIZE HORIZONTAL CURSOR POSITION DIR$ #GMCR ;TRY TO GET AN MCR COMMAND LINE BCS 5$ ;BR IF COUNLDN'T MOVB $DSW,R1 ;GET LENGTH OF INPUT BLE 5$ ;BR IF NONE MOV #GMCR+G.MCRB,R0 ;POINT AT COMMAND LINE ;RBD02+ 1$: TSTB (R0) ;SCAN TILL NULL BEQ 5$ ;(IF NULL FOUND 1ST, NO FILENAME GIVEN) DEC R1 CMPB (R0)+,#' ;OR FIRST BLANK BNE 1$ ;RBD02- CALL CMDOSF ;OPEN THE SPECIFIED FILE 5$: MOV #1,REPCT ;INITIALIZE THE REPEAT COUNTER MOV #1,R0 ;SET "ENTIRE BUFFER" SWITCH CALL DSPBF ;DISPLAY ENTIRE BUFFER CALL INCHR ;INITIALIZE WITH FIRST CHARACTER CALL GETCMD ;ENTER COMMAND INPUT AND INTERPRETER MOV #'>,R0 ;EXIT ALTERNATE KEYPAD MODE CALL DSPES ;DO IT MOV #'G,R0 ;EXIT GRAPHICS MODE (IN CASE) CALL DSPES ;DO IT CALL CLRSC ;CLEAR THE SCREEN MOV #ICEEXB,R0 ;POINT AT EXIT MESSAGE CALL DSPMS ;DISPLAY IT BR 20$ 10$: CALL CLRSC ;CLEAR THE SCREEN MOV #ICEATB,R0 ;CANNOT ATTACH TI: CALL DSPMS ;DISPLAY IT 20$: EXIT$S .SBTTL GETCMD - COMMAND INTERPRETER ;+ ; -GETCMD- COMMAND INTERPRETATION ROUTINE ; ; THIS ROUTINE GETS COMMANDS FROM THE USER, AND EXECUTES THEM. ; IT RETURNS TO THE CALLER ONLY WHEN A COMMAND WHICH REQUIRES ; AN EXIT TO BE PERFORMED IS RECEIVED. ; ; ALL REGISTERS EXCEPT R3 MUST BE SAVED BY THE COMMAND ROUTINES. ; ; AS INPUT TO THE COMMAND ROUTINES: ; REGISTER R0 CONTAINS THE CURRENT INPUT CHARACTER ; REGISTER R3 CONTAINS THE CURRENT HORIZONTAL CURSOR POSITION ; BFPOS, BFCUR, BFTOP, AND BFBOT ARE SET PROPERLY ; ; AS OUTPUT FROM THE COMMAND ROUTINES: ; R0 CONTAINS INPUT TO THE "DSPBF" ROUTINE ; R3 CONTAINS THE CURRENT HORIZONTAL CURSOR POSITION ; BFPOS, BFCUR, BFTOP, AND BFBOT ARE SET PROPERLY ; REPCT MAY BE MODIFIED ;- GETCMD: MOV #CMDTBL,R5 ;POINT AT FIRST COMMAND TABLE BIT #FL.MCD,FLAGS ;IS A MESSAGE UP? BEQ 10$ ;BR IF NO CALL CLRBT ;CLEAR THE BOTTOM LINE BIC #FL.MCD,FLAGS ;NO MORE MESSAGE MOV #SC.CUR,R2 ;SET TO CURSOR LINE CALL DSPPS ;RESET POSITION 10$: CMPB R0,(R5)+ ;DO ENTRY AND CHARACTER MATCH? BEQ 20$ ;BR IF YES TSTB -(R5) ;DOES ENTRY MATCH ALL CHARACTERS? BMI 15$ ;BR IF YES CMP (R5)+,(R5)+ ;SKIP ENTRY BR 10$ ;TRY NEXT 15$: INC R5 ;POINT AT FLAGS BYTE 20$: BITB #FC.ICB,(R5) ;INPUT CHARACTER BEFORE EXECUTION? BEQ 25$ ;BR IF NO CALL INCHR ;INPUT A CHAR 25$: BITB #FC.TBL,(R5)+ ;JUST CHANGE COMMAND TABLES? BEQ 30$ ;BR IF NO MOV (R5),R5 ;SWITCH TO NEW TABLE BR 10$ ;START AGAIN 30$: BIT #FL.RPM,FLAGS ;ARE WE IN REPLACE MODE? BEQ 35$ ;BR IF NO BITB #FC.IDR,-1(R5) ;IS OPERATION ILLEGAL NOW? BEQ 35$ ;BR IF NO MOV #EIDRB,R0 ;INDICATE OPERATION IS ILLEGAL CALL DSPMS ;TELL USER MOV #SC.CUR,R2 ;POINT AT NORMAL LINE CALL DSPPS ;MOVE CURSOR BACK CLR R0 ;NO DISPLAY UPDATE BR 40$ ;ACT AS IF COMMAND WAS DONE 35$: MOV R5,-(SP) ;SAVE ENTRY ADDRESS CALL @(R5)+ ;CALL COMMAND ROUTINE MOV (SP)+,R5 ;RESTORE ENTRY ADDRESS 40$: ROR R4 ;SAVE CARRY BIT BIC #FL.LCS,FLAGS ;LAST COMMAND WAS NOT A SEARCH BITB #FC.SCH,-(R5) ;WAS I RIGHT? BEQ 45$ ;BR IF YES BIS #FL.LCS,FLAGS ;NO, LAST COMMAND WAS A SEARCH 45$: BITB #FC.RET,(R5) ;RETURN ON CARRY SET? BEQ 50$ ;BR IF NO TST R4 ;IS CARRY SET? BMI 65$ ;BR IF YES 50$: CALL DSPBF ;OUTPUT PROPER DISPLAY CHANGES MOV INLST,R0 ;IN CASE NEW CHAR NOT TO BE INPUT BITB #FC.ICA,(R5) ;INPUT CHARACTER AFTER EXECUTION? BNE 55$ ;BR IF YES BITB #FC.ICI,(R5) ;INPUT IF CARRY SET? BEQ 60$ ;BR IF NO TST R4 ;IS CARRY SET? BPL 60$ ;BR IF NO 55$: CALL INCHR ;INPUT A NEW CHAR 60$: BITB #FC.NRP,(R5) ;RESET REPEAT COUNT? BNE GETCMD ;BR IF NO, INTERPRET NEW COMMAND MOV #1,REPCT ;RESET COUNT TO ONE BR GETCMD ;INTERPRET NEW COMMAND 65$: RETURN ;RETURN TO MAIN ROUTINE (EXIT) .SBTTL CMD - SET REPEAT COUNT ;+ ; -CMDZRC- ZERO REPEAT COUNT ; -CMDNRC- SET NEGATIVE REPEAT COUNT ; -CMDPRC- SET POSITIVE REPEAT COUNT ;- CMDZRC: CLR REPCT ;ZERO THE COUNT CLR R0 ;NO DISPLAY CHANGE RETURN .ENABL LSB CMDNRC: MOV R4,-(SP) ;SAVE R4 MOV R5,-(SP) ;SAVE R5 MOV #-1,R5 ;SET NEGATE SWITCH MOV R5,R4 ;IN CASE NO DIGITS CALL INCHR ;GET NEXT CHAR CMP #'0,R0 ;IS CHAR IN NUMERIC RANGE? BGT 35$ ;BR IF NO, USE -1 CMP #'9,R0 ;MAKE SURE BLT 35$ ;BR IF NO, USE -1 BR 10$ ;INTERPRET NORMALLY CMDPRC: MOV R4,-(SP) ;SAVE R4 MOV R5,-(SP) ;SAVE R5 CLR R5 ;SET NO NEGATE SWITCH 10$: CLR R4 ;ZERO NEW REPEAT COUNT 20$: CMP #'0,R0 ;IN NUMERIC RANGE? BGT 30$ ;BR IF NO, FINISHED CMP #'9,R0 ;MAKE SURE BLT 30$ ;BR IF NO, FINISHED SUB #'0,R0 ;MAKE BINARY ASL R4 ;MULTIPLY COUNT BY 10. MOV R4,-(SP) ;... ASL R4 ;... ASL R4 ;... ADD (SP)+,R4 ;... ADD R0,R4 ;ADD IN NEW DIGIT CALL INCHR ;GET NEW CHARACTER BR 20$ ;INTERPRET IT 30$: TST R5 ;NEGATE? BEQ 35$ ;BR IF NO NEG R4 ;NEGATE THE COUNT 35$: MOV R4,REPCT ;SET THE COUNT MOV (SP)+,R5 ;RECOVER R5 MOV (SP)+,R4 ;RECOVER R4 CLR R0 ;NO DISPLAY CHANGES RETURN .DSABL LSB .SBTTL CMD - NO-OP, REFRESH, SET NUMBER OF COLUMNS ;+ ; -CMDNOP- COMMAND IS A NO-OP ;- CMDNOP: CLR R0 ;DISPLAY DOES NOT CHANGE RETURN ;+ ; -CMDDSP- DISPLAY BUFFER ON SCREEN (REFRESH) ;- CMDDSP: MOV #1,R0 ;DISPLAY ENTIRE BUFFER RETURN .SBTTL CMD - CLOSE AND OPEN NEW FILE ;+ ; -CMDCAR- CLOSE AND REOPEN OLD FILE ; -CMDOSF- OPEN PRE-SPECIFIED FILE ; -CMDCAO- CLOSE OLD FILE (IF ANY) AND OPEN NEW ;- .ENABL LSB CMDCAR: MOV R1,-(SP) ;SAVE R1 MOV R4,-(SP) ;SAVE R4 CALL CMDCAE ;CLOSE OUTPUT FILE BR 5$ CMDOSF: MOV R1,-(SP) ;SAVE R1 MOV R4,-(SP) ;SAVE R4 BR 3$ ;OPEN SPECIFIED FILE CMDCAO: MOV R1,-(SP) ;SAVE R1 MOV R4,-(SP) ;SAVE R4 CALL CMDCAE ;PRETEND WE ARE CLOSING AND EXITING MOV #ENFNB,R0 ;SET MESSAGE ADDRESS CALL DSPMS ;ASK FOR FILE NAME MOV #IOFSTR,R0 ;POINT AT THE FILE NAME STRING BUFFER MOV #IOFLEN,R1 ;GET ITS LENGTH CALL INLIN ;GET INPUT FROM USER BCS 30$ ;BR IF TYPED CONTROL-Z CALL CNVLUC ;CONVERT CHARACTERS TO UPPER CASE 3$: MOV #IOFNAM,R4 ;POINT AT NAME BLOCK CALL PRSFL ;PARSE THE FILE NAME CALL CLRBT ;CLEAR THE BOTTOM LINE 5$: BIS #FL.IFO+FL.OFO,FLAGS ;ASSUME THEY BOTH OPEN OPEN$ #INPFDB ;OPEN THE INPUT FILE BCS 7$ ;BR IF NOT FOUND ;RBD05+ MOV IOFNAM+12,R0 ;R0 --> "FILENAME.EXT;VER" MOV IOFNAM+10,R1 ;R1 = LENGTH OF "...." CLR R4 ;R4 WILL BE NEW BYTE COUNT 6$: CMPB (R0)+,#'; ;LOOK FOR ";" BEQ 65$ INC R4 DEC R1 BGT 6$ 65$: MOV R4,IOFNAM+10 ;POSSIBLY ADJUST BYTE COUNT BR 8$ ;NOW GO OPEN VERSIONLESS ;RBD05- 7$: BIC #FL.IFO,FLAGS ;NO INPUT FILE MOV #ECNFB,R0 ;CREATING NEW FILE CALL DSPMS ;DISPLAY THE MESSAGE 8$: OPEN$ #OUTFDB ;OPEN THE OUTPUT FILE BCS 25$ ;BR IF CAN'T BIT #FL.PAG,FLAGS ;DO WE HAVE A FULL PAGE HERE? BNE 30$ ;BR IF YES CLR R0 ;GIVE MESSAGES CALL RDPAG ;READ IN A PAGE BR 30$ 25$: CLOSE$ #INPFDB ;CLOSE THE INPUT FILE BIC #FL.IFO+FL.OFO,FLAGS ;NOTHING OPEN MOV #ENSFB,R0 ;FILE OPEN ERROR CALL DSPMS 30$: MOV (SP)+,R4 ;RESTORE R4 MOV (SP)+,R1 ;RESTORE R1 MOV #1,R0 ;DISPLAY ENTIRE BUFFER RETURN .DSABL LSB .SBTTL CMD - KILL/END/CLOSE EDIT, DELETE INPUT FILE ;+ ; -CMDKIL- KILL EDIT ; -CMDEOF- END OUTPUT FILE ; -CMDCDI- CLOSE AND DELETE INPUT FILE ; -CMDCAE- CLOSE AND POSSIBLY EXIT ;- .ENABL LSB CMDKIL: CALL CLRSC ;CLEAR THE SCREEN MOV R1,-(SP) ;SAVE R1 MOV #EKILB,R0 ;ADDRESS OF MESSAGE CALL ASKSR ;ASK IF USER IS SURE MOV (SP)+,R1 ;RESTORE R1 CMPB #'Y,R0 ;DID HE SAY YES? BEQ 3$ ;BR IF YES CLC ;NO EXIT BR 40$ ;RETURN TO SENDER 3$: CALL CLRSC ;CLEAR THE SCREEN MOV BFTOP,R0 ;GET THE TOP LINE BEQ 10$ ;BR IF NONE 5$: MOV (R0),-(SP) ;SAVE THE LINK TO NEXT CALL RETBF ;RETURN THE BUFFER MOV (SP)+,R0 ;GET ADDRESS OF NEXT BNE 5$ ;BR IF GOT ONE 10$: CLR BFTOP ;NO TOP LINE CLR BFBOT ;NO BOTTOM LINE CLR BFCUR ;NO CURRENT LINE CLR BFPOS ;BEFORE FIRST CHAR ON LINE CLR R3 ;AT LEFT OF SCREEN BIT #FL.OFO,FLAGS ;IS AN OUTPUT FILE OPEN? BEQ 30$ ;BR IF NO DELET$ #OUTFDB ;DELETE THE OUTPUT FILE BR 30$ CMDCDI: CALL CLRSC ;CLEAR THE SCREEN MOV R1,-(SP) ;SAVE R1 ;RBD04+ MOV #ECDIB,R0 ;ADDRESS OF MESSAGE CALL ASKSR ;ASK USER IF HE'S SURE MOV (SP)+,R1 ;RESTORE R1 CMPB #'Y,R0 ;'YES' IS U.C.'Y'... ONLY BEQ 12$ CLC ;NOT SURE, DON'T EXIT BR 40$ ;ABORT THE COMMAND 12$: MOV #1,R0 ;NO MESSAGES ;RBD04- 15$: CALL WTPAG ;WRITE A PAGE BCS 30$ ;BR IF NO FILE OPEN CALL RDPAG ;READ A PAGE BCC 15$ ;BR IF OK BIT #FL.IFO,FLAGS ;IS AN INPUT FILE OPEN? BEQ 25$ ;BR IF NO DELET$ #INPFDB ;DELETE THE INPUT FILE BR 25$ ;GO CLOSE THE OUTPUT FILE CMDEOF: MOV R1,-(SP) ;SAVE R1 MOV #EENDB,R0 ;ADDRESS OF MESSAGE CALL ASKSR ;ASK IF USER IS SURE MOV (SP)+,R1 ;RESTORE R1 CMPB #'Y,R0 ;DID HE SAY YES? BNE 35$ ;BR IF NO CLOSE$ #INPFDB ;CLOSE INPUT FILE SO CAN'T READ BIC #FL.IFO,FLAGS ;NO INPUT FILE OPEN CMDCAE: CALL CLRSC ;CLEAR THE SCREEN MOV #1,R0 ;NO MESSAGES 20$: CALL WTPAG ;WRITE OUT CURRENT PAGE BCS 25$ ;BR IF NO OUTPUT FILE CALL RDPAG ;READ IN A NEW PAGE BCC 20$ ;BR IF GOT A NEW PAGE 25$: CLOSE$ #OUTFDB ;CLOSE THE OUTPUT FILE 30$: CLOSE$ #INPFDB ;CLOSE THE INPUT FILE SM.TMP= FL.IFO+FL.OFO ;SET A SYMBOL FOR ALL FLAGS SM.TMP= SM.TMP+FL.EOF+FL.PAG ;THAT MUST BE CLEARED BIC #SM.TMP,FLAGS ;CLEAR ALL NECESSARY FLAGS 35$: SEC ;INDICATE "EXIT" IF NECESSARY 40$: MOV #1,R0 ;UPDATE DISPLAY RETURN .DSABL LSB .SBTTL CMD - WRITE LINES TO OUTPUT FILE ;+ ; -CMDSTO- WRITE LINES AT TOP OF BUFFER TO OUTPUT FILE ;- CMDSTO: TST REPCT ;LEGAL COUNT? BLE 40$ ;BR IF NO, DO NOTHING BIT #FL.OFO,FLAGS ;IS AN OUTPUT FILE OPEN? BEQ 35$ ;BR IF NO 10$: MOV BFTOP,R0 ;GET THE TOP LINE BEQ 20$ ;BR IF NONE CMP R0,BFCUR ;IS IT OUR CURRENT LINE? BNE 15$ ;BR IF NO MOV #1,BFCUR ;FAKE CURRENT LINE 15$: MOV (R0),BFTOP ;RESET THE TOP LINE CALL PUTLN ;PUT THE TOP LINE DEC REPCT ;ANY MORE? BGT 10$ ;BR IF YES 20$: MOV BFTOP,R0 ;GET TOP LINE BEQ 25$ ;BR IF NONE, NOW CLR 2(R0) ;NO BACK LINK BR 28$ 25$: CLR BFBOT ;NO BOTTOM LINE 28$: CMP #1,BFCUR ;FAKE CURRENT LINE? BNE 30$ ;BR IF NO MOV R0,BFCUR ;RESET TO NEW TOP LINE (OR NONE) CLR BFPOS ;AT BEGINNING OF LINE CLR R3 ;AT FAR LEFT OF SCREEN 30$: MOV #ESCRB,R0 ;TELL USER SCROLLED CALL DSPMS ;DISPLAY MESSAGE MOV #1,R0 ;REFRESH SCREEN BR 45$ 35$: MOV #ENOFB,R0 ;NO OUTPUT FILE CALL DSPMS ;DISPLAY MESSAGE MOV R2,-(SP) ;SAVE R2 MOV #SC.CUR,R2 ;POINT AT CURSOR LINE CALL DSPPS ;RESET CURSOR MOV (SP)+,R2 ;RESTORE R2 40$: CLR R0 ;NO SCREEN UPDATE 45$: RETURN .SBTTL CMD - SCROLL ;RBD04+ ;+ ; -CMDSCR- SCROLL. WRITE/READ LINES. STOP AT ;- CMDSCR: MOV #NM.SCR,REPCT ;SET # LINES TO DO CALL CMDSTO ;WRITE 'EM TO THE OUTPUT TST R0 ;WRITTEN OK? BEQ 30$ ;IF NOT, RETURN R0=0 CALL CMDANP ;APPEND NEXT PAGE MOV #1,R0 ;REDISPLAY ENTIRE BUFFER 30$: RETURN .SBTTL CMD - DELETE CURRENT LINE ;+ ; -CMDDCL- DELETE CURRENT LINE ; CMDDCL: CALL CMDBOL ;BEGINNING OF LINE JMP CMDDAL ;DELETE LINES AND APPEND ;RBD04- .SBTTL CMD - CENTER TEXT ON THE N'TH COLUMN ;+ ; -CMDCTR- CENTER THE CURRENT LINE OF TEXT ON THE N'TH COLUMN ;- CMDCTR: MOV BFCUR,R0 ;GET CURRENT LINE BEQ 10$ ;BR IF NONE, NO SCREEN UPDATE MOV 4(R0),R0 ;GET NUMBER OF CHARS ON LINE BEQ 10$ ;BR IF NONE, NO SCREEN UPDATE ASR R0 ;DEVIDE BY 2 CMP #1,REPCT ;HOW IS REPCT BLT 5$ ;BR IF ALREADY SET MOV NMCOL,REPCT ;SET TO NUMBER OF COLUMNS 5$: ASR REPCT ;DEVIDE NUMBER COLUMNS BY 2 SUB R0,REPCT ;NUMBER OF SPACES TO SHIFT OVER CALL CMDBOL ;MOVE TO BEGINNING OF LINE CLR R0 ;IN CASE NO INSERT TST REPCT ;CHECK THE COUNT BLE 10$ ;BR IF NOTHING, NO SCREEN UPDATE MOV #40,R0 ;INSERT SOME SPACES CALL CMDINS ;GO INSERT THEM 10$: RETURN .SBTTL CMD - INSERT THE TYPED CHARACTER INTO THE LINE ;+ ; -CMDICV- INSERT NEXT CHARACTER VERBATIM ; -CMDIPM- INSERT PAGE MARK ; -CMDINS- CHARACTER IS TO BE INSERTED INTO THE LINE ;- CMDICV: CALL INCHR ;GET NEXT CHARACTER BR CMDINS ;INSERT IT CMDIPM: MOV #14,R0 ;SET INPUT CHAR TO PAGE MARK CMDINS: MOV R1,-(SP) ;SAVE R1 MOV R2,-(SP) ;SAVE R2 MOV R4,-(SP) ;SAVE R4 MOV R5,-(SP) ;SAVE R5 CLR -(SP) ;R0 ARG. FOR EXIT (NO SCREEN UPDATE) TST REPCT ;VALID REPEAT COUNT? BLE 30$ ;BR IF NO MOV #3,(SP) ;SET TO PRINT END OF LINE MOV R0,R1 ;COPY CHARACTER MOV BFCUR,R5 ;GET CURRENT LINE BNE 10$ ;BR IF OK CALL CMDONL ;SIMULATE "OPEN NEW LINE" MOV R0,(SP) ;USE SUGGESTED SCREEN UPDATE ARG. MOV BFCUR,R5 ;NOW GET CURRENT LINE BEQ 30$ ;FAILED COMPLETELY 10$: BIT #FL.RPM,FLAGS ;ARE WE IN REPLACE MODE? BEQ 11$ ;BR IF NO MOV REPCT,-(SP) ;SAVE THE CURRENT REPEAT COUNT CALL CMDDCC ;DELETE THE CURRENT CHARACTERS MOV (SP)+,REPCT ;RESTORE THE REPEAT COUNT 11$: ADD #4,R5 ;POINT AT BYTE COUNT MOV (R5),-(SP) ;SAVE CURRENT BYTE COUNT ADD REPCT,(SP) ;ADD IN NEW CHARACTERS CMP (SP)+,#NM.CHR ;IS NEW COUNT LEGAL? BGT 20$ ;BR IF NO MOV R5,R4 ;SACRIFICE R4 TST (R4)+ ;POINT AT LINE ADD (R5),R4 ;POINT AT POSITION AFTER LAST MOV (R5),R2 ;GET CHARACTER COUNT ADD REPCT,(R5) ;SET NEW CHARACTER COUNT SUB BFPOS,R2 ;GET COUNT OF CHARS AT END MOV R2,-(SP) ;SAVE THE COUNT BEQ 13$ ;BR IF NONE MOV R4,R5 ;COPY POINTER TO POSITION AFTER LAST ADD REPCT,R5 ;POINT TO NEW POSITION AFTER LAST 12$: MOVB -(R4),-(R5) ;MOVE CHARACTERS DOWN DEC R2 ;COUNT THEM BGT 12$ ;BR IF MORE 13$: CALL CLRLN ;CLEAR THE END OF THE LINE MOV R4,R5 ;SAVE POINTER TO INSERTION MOV REPCT,R2 ;GET REPEAT COUNT MOV R1,R0 ;GET INSERT CHARACTER BACK 14$: MOVB R0,(R5)+ ;MOVE IN NEW CHARACTERS CALL DSPCR ;DISPLAY THE NEW CHARACTER DEC R2 ;COUNT DOWN BGT 14$ ;BR IF MORE TO MOVE ADD REPCT,BFPOS ;RESET THE LINE POSITION TST (SP)+ ;ANY CHARS AT END OF LINE TO DISPLAY? BNE 30$ ;BR IF YES, ALREADY SET CMP #3,(SP) ;ONLY SET TO DISPLAY END OF LINE? BNE 30$ ;BR IF NO, LEAVE SETTING ALONE CLR (SP) ;SET TO DISPLAY NOTHING BR 30$ 20$: MOV #NLINB,R0 ;NO ROOM ON LINE CALL DSPMS ;DISPLAY THE MESSAGE MOV #SC.CUR,R2 ;SET TO CURSOR LINE CALL DSPPS ;SET POSITION CLR (SP) ;DO NOT CHANGE DISPLAY 30$: MOV (SP)+,R0 ;GET DISPLAY ARGUMENT MOV (SP)+,R5 ;RECOVER R5 MOV (SP)+,R4 ;RECOVER R4 MOV (SP)+,R2 ;RECOVER R2 MOV (SP)+,R1 ;RECOVER R1 RETURN .SBTTL CMD - ENTER OR EXIT REPLACE MODE ;+ ; -CMDERM- ENTER REPLACE MODE ; -CMDXRM- EXIT REPLACE MODE ;- .ENABL LSB CMDERM: BIS #FL.RPM,FLAGS ;ENTER REPLACE MODE MOV #EERMB,R0 ;ENTERING REPLACE MODE BR 10$ CMDXRM: BIC #FL.RPM,FLAGS ;EXIT REPLACE MODE MOV #EXRMB,R0 ;EXITING REPLACE MODE 10$: MOV R2,-(SP) ;SAVE R2 CALL DSPMS ;INFORM USER MOV #SC.CUR,R2 ;NORMAL COLUMN CALL DSPPS ;RESET POSITION MOV (SP)+,R2 ;RESTORE R2 CLR R0 ;NO SCREEN CHANGE RETURN .DSABL LSB .SBTTL CMD - CLEAR AND INSERT INTO SAVE BUFFER ;+ ; -CMDCSB- CLEAR OUT SAVE BUFFER ; -CMDISB- INSERT TEXT IN SAVE BUFFER ;- CMDCSB: MOV SVTOP,R0 ;POINT AT TOP SAVE LINE BEQ 10$ ;BR IF NONE MOV (R0),SVTOP ;RESET TOP LINE CALL RETBF ;RETURN THE BUFFER BR CMDCSB ;DO AGAIN 10$: CLR SVBOT ;NO BOTTOM POINTER MOV #ESBCB,R0 ;INFORM USER CALL DSPMS ;SAVE BUFFER CLEARED MOV R2,R0 ;SAVE R2 MOV #SC.CUR,R2 ;SET TO NORMAL LINE CALL DSPPS ;RESET THE CURSOR MOV R0,R2 ;RESTORE R2 CLR R0 ;NO SCREEN CHANGE RETURN CMDISB: MOV R1,-(SP) ;SAVE R1 MOV R2,-(SP) ;SAVE R2 MOV R4,-(SP) ;SAVE R4 MOV BFCUR,R1 ;POINT AT CURRENT LINE BEQ 40$ ;BR IF NONE MOV BFPOS,R4 ;SET THE POSITION IN THE LINE 10$: CALL GETBF ;GET A LINE BUFFER BCS 45$ ;BR IF NONE TO GET MOV (R1),-(SP) ;SAVE ADDRESS OF NEXT LINE CMP (R1)+,(R1)+ ;POINT AT BYTE COUNT MOV (R1)+,R2 ;GET THE COUNT SUB R4,R2 ;BYTES AT END OF LINE ADD R4,R1 ;POINT AT THEM TST SVBOT ;IS THERE A BOTTOM SAVED LINE? BNE 20$ ;BR IF YES MOV R0,SVTOP ;SET THE TOP SAVE LINE CLR 2(R0) ;NO BACK POINTER BR 25$ ;SKIP NEXT 20$: MOV R0,@SVBOT ;SET PREVIOUS LINES FORWARD POINTER MOV SVBOT,2(R0) ;SET BACK POINTER 25$: MOV R0,SVBOT ;SET NEW BOTTOM LINE CLR (R0)+ ;NO FORWARD LINK TST (R0)+ ;SKIP THE BACK LINK MOV R2,(R0)+ ;SET THE BYTE COUNT BEQ 35$ ;BR IF NOTHING TO SAVE 30$: MOVB (R1)+,(R0)+ ;SAVE THE TEXT DEC R2 ;COUNT BYTES BGT 30$ ;BR IF MORE 35$: MOV (SP)+,R1 ;GET ADDRESS OF NEXT LINE TO SAVE BEQ 40$ ;BR IF NONE CLR R4 ;NO LONGER IN MIDDLE OF LINE DEC REPCT ;SAVED ENOUGH YET? BGT 10$ ;BR IF NO 40$: MOV #ESAVB,R0 ;INDICATE THAT TEXT HAS BEEN SAVED BR 50$ ;GO DISPLAY MESSAGE 45$: MOV #NBUFB,R0 ;NO AVAILABLE BUFFER 50$: CALL DSPMS ;DISPLAY THE MESSAGE MOV #SC.CUR,R2 ;SET TO NORMAL LINE CALL DSPPS ;MOVE CURSOR BACK CLR R0 ;NO SCREEN CHANGE MOV (SP)+,R4 ;RESTORE R4 MOV (SP)+,R2 ;RESTORE R2 MOV (SP)+,R1 ;RESTORE R1 RETURN .SBTTL CMD - UNSAVE TEXT ;+ ; -CMDULN- UNSAVE AND CLEAR A LINE FROM THE SAVE BUFFER ; -CMDUSB- UNSAVE ALL CONTENTS OF SAVE BUFFER (DON'T CLEAR IT) ;- CMDULN: MOV SVTOP,R0 ;GET TOP LINE BEQ 25$ ;BR IF NONE MOV (R0),SVTOP ;RESET THE TOP LINE BNE 10$ ;BR IF MORE STILL IN BUFFER CLR SVBOT ;NO TOP OR BOTTOM BR 15$ ;SKIP THE CLEAR IN NO NEXT BUFFER 10$: MOV R1,-(SP) ;SAVE R1 MOV (R0),R1 ;POINT AT NEXT BUFFER CLR 2(R1) ;CLEAR NEXT BUFFER'S BACK POINTER MOV (SP)+,R1 ;RESTORE R1 15$: CALL SBFSUB ;CALL COMMON SUBROUTINE CALL RETBF ;RETURN THE BUFFER MOV #2,R0 ;UPDATE END OF SCREEN 25$: RETURN CMDUSB: MOV SVBOT,R0 ;GET BOTTOM LINE BEQ 20$ ;BR IF NONE 10$: CALL SBFSUB ;CALL COMMON SUBROUTINE MOV 2(R0),R0 ;POINT AT NEXT UP BNE 10$ ;BR IF ONE EXISTS MOV #2,R0 ;UPDATE END OF BUFFER 20$: RETURN SBFSUB: MOV R0,-(SP) ;SAVE R0 MOV R4,-(SP) ;SAVE R4 MOV R5,-(SP) ;SAVE R5 MOV R0,R4 ;SAVE THE LINE ADDRESS CALL CMDONL ;OPEN A NEW LINE CMP (R4)+,(R4)+ ;MOVE TO BYTE COUNT MOV (R4),-(SP) ;SAVE THE INSERT COUNT MOV (R4)+,R5 ;COPY IT BEQ 20$ ;BR IF NO INSERT 10$: MOV #1,REPCT ;DO ONCE MOVB (R4)+,R0 ;CHARACTER TO INSERT CALL CMDINS ;INSERT IT DEC R5 ;ANY MORE TO INSERT? BGT 10$ ;BR IF YES 20$: MOV (SP)+,REPCT ;NUMBER OF CHARACTERS INSERTED BEQ 30$ ;BR IF NONE CALL CMDMCL ;BACK UP BEFORE INSERTION 30$: MOV (SP)+,R5 ;RESTORE R5 MOV (SP)+,R4 ;RESTORE R4 MOV (SP)+,R0 ;RESTORE R0 RETURN .SBTTL CMD - GET NEXT PAGE ;+ ; -CMDGNP- GET NEXT PAGE FROM FILE ;- CMDGNP: MOV R1,-(SP) ;SAVE R1 MOV R2,-(SP) ;SAVE R2 CLR R0 ;IF ERROR, NO SCREEN CHANGE TST REPCT ;LEGAL REPEAT COUNT? BLE 35$ ;BR IF NO 10$: CALL WTPAG ;WRITE OUT CURRENT PAGE (IGNOR ERROR) BCS 29$ ;BR IF NO OUTPUT FILE CALL RDPAG ;READ IN NEXT PAGE (GIVE MESSAGES) BCS 30$ ;BR IF NO MORE DEC REPCT ;FINISHED? BGT 10$ ;BR IF NO BR 30$ 29$: MOV #ENOFB,R0 ;NO OUTPUT FILE OPEN CALL DSPMS ;DISPLAY MESSAGE CALL DSPPS ;RETURN TO NORMAL CURSOR POSITION CLR R0 ;NO DISPLAY CHANGE BR 35$ 30$: MOV #1,R0 ;REDISPLAY ENTIRE BUFFER 35$: MOV (SP)+,R2 ;RESTORE R2 MOV (SP)+,R1 ;RESTORE R1 RETURN .SBTTL CMD - DELETE START AND END OF PAGE, APPEND PAGE ;+ ; -CMDDAP- DELETE END OF PAGE AND APPEND NEXT PAGE ; -CMDANP- APPEND NEXT PAGE ; -CMDDBP- DELETE BEGINNING OF PAGE ; -CMDDEP- DELETE END OF PAGE ;- .ENABL LSB CMDDAP: CALL CMDDEP ;DELETE THE END OF THE PAGE CMDANP: CLR R0 ;OUTPUT MESSAGES CALL RDPAG ;READ IN NEXT PAGE MOV #2,R0 ;DISPLAY END OF BUFFER RETURN CMDDBP: CALL CMDDSL ;DELETE START OF LINE 10$: MOV BFTOP,R0 ;GET TOP LINE ADDRESS BEQ 12$ ;BR IF NONE CLR 2(R0) ;MAKE SURE NO BACK POINTER CMP R0,BFCUR ;IS IT OUR CURRENT LINE? BEQ 15$ ;BR IF YES MOV (R0),BFTOP ;RESET TOP LINE CALL RETBF ;RETURN THE LINE BUFFER BR 10$ ;CHECK NEXT 12$: CLR BFBOT ;BUFFER NOW EMPTY CLR BFCUR ;NO CURRENT LINE CLR BFPOS ;SITTING AT LEFT CLR R3 ;ON LEFT OF SCREEN 15$: MOV #1,R0 ;DISPLAY ENTIRE BUFFER TST BFTOP ;ANY LINES LEFT? BEQ 30$ ;BR IF NO, SEE IF PAGE MARK NEEDED BR 40$ CMDDEP: TST BFPOS ;AT BEGINNING OF LINE? BEQ 20$ ;BR IF YES CALL CMDDEL ;DELETE END OF LINE CALL CLRLN ;CLEAR THE END OF THE LINE MOV #1,REPCT ;DO ONCE CALL CMDBNL ;MOVE TO BEGINNING OF NEXT LINE 20$: MOV #NM.LIN,REPCT ;FOR ALL FOLLOWING LINES CALL CMDDAL ;DELETE AND APPEND MOV #2,R0 ;DISPLAY END OF BUFFER 30$: BIT #FL.PAG,FLAGS ;DID BUFFER END WITH PAGE MARK? BEQ 40$ ;BR IF NO MOV R0,-(SP) ;SAVE R0 MOV #1,REPCT ;DO ONCE CALL CMDIPM ;INSERT A PAGE MARK CALL CMDBOP ;MOVE TO BOTTOM OF PAGE MOV (SP)+,R0 ;RESTORE R0 40$: RETURN .DSABL LSB .SBTTL CMD - CHANGE CHARACTER CASE ;+ ; -CMDCLC- CHANGE UPPER TO LOWER CASE ; -CMDCUC- CHANGE LOWER TO UPPER CASE ;- .ENABL LSB CMDCLC: MOV R4,-(SP) ;SAVE R4 MOV #1,R4 ;INDICATE UPPER TO LOWER CASE BR 5$ CMDCUC: MOV R4,-(SP) ;SAVE R4 CLR R4 ;INDICATE LOWER TO UPPER CASE 5$: MOV R1,-(SP) ;SAVE R1 MOV R2,-(SP) ;SAVE R2 MOV R5,-(SP) ;SAVE R5 MOV REPCT,R5 ;GET THE REPETITION COUNT BLE 30$ ;BR IF DO NO TIMES 10$: MOV BFCUR,R1 ;GET CURRENT LINE BEQ 30$ ;BR IF NONE, END OF BUFFER CMP (R1)+,(R1)+ ;POINT AT CHARACTER COUNT CMP BFPOS,(R1)+ ;IS CURRENT POSITION PAST END OF LINE? BLT 13$ ;BR IF NO MOV #1,REPCT ;SET REPEAT COUNT TO ONE CALL CMDBNL ;GO TO NEXT LINE BR 10$ ;DO THIS LINE 13$: ADD BFPOS,R1 ;POINT AT CHAR TO CONVERT TST R4 ;WHICH DIRECTION? BNE 15$ ;BR IF UPPER TO LOWER CASE CMPB (R1),#'A+40 ;IS CHARACTER LOWER CASE? BLT 20$ ;BR IF NO, SKIP IT CMPB (R1),#'Z+40 ;MUST BE IN ALPHA RANGE BGT 20$ ;BR IF NO BICB #40,(R1) ;CONVERT TO UPPER CASE BR 18$ 15$: CMPB (R1),#'A ;IS CHARACTER UPPER CASE? BLT 20$ ;BR IF NO CMPB (R1),#'Z ;MUST IN ALPHA RANGE BGT 20$ ;BR IF NO BISB #40,(R1) ;CONVERT TO LOWER CASE 18$: MOVB (R1),R0 ;GET CHARACTER MOV R3,R2 ;SAVE CURRENT COLUMN CALL DSPCR ;DISPLAY IT MOV R2,R3 ;RESTORE OLD COLUMN MOV #30,R2 ;STAY ON SAME LINE CALL DSPPS ;RESET POSITION 20$: MOV #1,REPCT ;DO ONLY ONCE CALL CMDMCR ;MOVE CURSOR TO RIGHT DEC R5 ;DECREMENT REPEAT COUNT BGT 10$ ;BR IF MORE TO GO 30$: MOV (SP)+,R5 ;RESTORE R5 MOV (SP)+,R2 ;RESTORE R2 MOV (SP)+,R1 ;RESTORE R1 MOV (SP)+,R4 ;RESTORE R4 CLR R0 ;NO SCREEN UPDATE NECESSARY RETURN .DSABL LSB .SBTTL CMD - FIND NEXT WORD ;+ ; -CMDFNW- FIND NEXT WORD ;- CMDFNW: MOV R1,-(SP) ;SAVE R1 MOV R4,-(SP) ;SAVE R4 MOV R5,-(SP) ;SAVE R5 MOV #BFSCH,R1 ;POINT AT SEARCH TEXT BUFFER MOV #BFTMP,R4 ;POINT AT TEMP SAVE BUFFER MOV (R1),R5 ;GET THE COUNT MOV (R1)+,(R4)+ ;SAVE THE COUNT 10$: MOVB (R1)+,(R4)+ ;MOVE THE CURRENT SEARCH TEXT DEC R5 ;IN ORDER TO SAVE IT BGT 10$ ;BR IF MORE TO MOVE MOV #1,BFSCH ;SET THE SEARCH COUNT TO ONE MOV REPCT,R5 ;KEEP THE REPETITION COUNT 20$: MOV #2,BFSCH+2 ;LOOK FOR A NON-ALPHANUMERIC MOV #1,REPCT ;ONLY ONCE CALL CMDSFT ;SEARCH FOR IT CALL DSPBF ;KEEP UPDATING THE SCREEN MOV #1,BFSCH+2 ;LOOK FOR AN ALPHANUMERIC MOV #1,REPCT ;ONLY ONCE CALL CMDSFT ;SEARCH FOR IT CALL DSPBF ;KEEP UPDATING THE SCREEN MOV #1,REPCT ;DO ONLY ONCE CALL CMDMCL ;BACK UP TO START OF WORD DEC R5 ;COUNT TIMES DONE BGT 20$ ;BR IF DO MORE MOV #BFSCH,R1 ;POINT AT SEARCH TEXT BUFFER MOV #BFTMP,R4 ;POINT AT SAVED SEARCH TEXT MOV (R4),R5 ;GET THE COUNT MOV (R4)+,(R1)+ ;RESTORE THE COUNT 30$: MOVB (R4)+,(R1)+ ;RESTORE THE TEXT DEC R5 ;COUNT DOWN BGT 30$ ;BR IF MORE MOV (SP)+,R5 ;RESTORE R5 MOV (SP)+,R4 ;RESTORE R4 MOV (SP)+,R1 ;RESTORE R1 CLR R0 ;NO MORE SCREEN UPDATES RETURN ;LEAVE R0 ALONE .SBTTL CMD - ENTER SEARCH AND REPLACE TEXT ;+ ; -CMDIST- ENTER TEXT TO SEARCH FOR ; -CMDIRT- ENTER TEXT TO REPLACE SEARCHES WITH ;- .ENABL LSB CMDIST: MOV R1,-(SP) ;SAVE R1 MOV R4,-(SP) ;SAVE R4 MOV #BFSCH,R0 ;INPUT BUFFER ADDRESS MOV R0,-(SP) ;SAVE IT ON THE STACK MOV #ESRTB,-(SP) ;OUTPUT BUFFER ADDRESS ON STACK BR 10$ ;EXECUTE COMMON CODE CMDIRT: MOV R1,-(SP) ;SAVE R1 MOV R4,-(SP) ;SAVE R4 MOV #BFREP,R0 ;INPUT BUFFER ADDRESS MOV R0,-(SP) ;SAVE IT ON THE STACK MOV #ERPTB,-(SP) ;OUTPUT BUFFER ADDRESS ON STACK 10$: MOV (R0)+,R1 ;GET THE NUMBER OF CHARS IN BUFFER MOV #BFTMP,R4 ;TEMPORARY SAVE BUFFER 20$: MOVB (R0)+,(R4)+ ;SAVE CONTENTS OF BUFFER DEC R1 ;MOVE ALL BYTES BGT 20$ ;BR IF MORE MOV (SP)+,R0 ;ADDRESS OF OUTPUT BUFFER CALL DSPMS ;PRINT THE QUESTION MOV (SP)+,R0 ;ADDRESS OF INPUT BUFFER TST (R0)+ ;SKIP BYTE COUNT MOV #NM.STL,R1 ;LENGTH OF BUFFER CALL INLIN ;GET SOME INPUT BCS 30$ ;BR IF USER DECIDED NOT TO MOV R1,-(R0) ;SET THE BYTE COUNT CALL CLRBT ;CLEAR THE BOTTOM LINE MOV #SC.CUR,R2 ;PLACE CURSOR BACK WHERE IT WAS CALL DSPPS ;MOVE THE CURSOR CLR R0 ;SCREEN IS NOT TO BE CHANGED CMP R4,#33 ;WAS INPUT ENDED BY AN ESCAPE? BNE 40$ ;BR IF NO MOV R4,INLST ;MAKE IT THE LAST CHAR INPUT CLC ;NO NEED TO INPUT NEW CHARACTER BR 45$ ;DONE 30$: MOV #BFTMP,R4 ;POINT AT TEMPORARY SAVE BUFFER MOV -2(R0),R1 ;GET THE OLD CHARACTER COUNT 35$: MOVB (R4)+,(R0)+ ;MOVE OLD DATA BACK IN AGAIN DEC R1 ;EVERY LAST BYTE BGT 35$ ;BR IF MORE MOV #1,R0 ;SET TO DISPLAY ENTIRE BUFFER 40$: SEC ;INPUT NEW COMMAND CHARACTER 45$: MOV (SP)+,R4 ;RESTORE R4 MOV (SP)+,R1 ;RESTORE R1 RETURN .DSABL LSB .SBTTL CMD - SEARCH FOR TEXT ;+ ; -CMDSFT- SEARCH FOR TEXT ; ; NOTE: ^A INDICATES ANY ALPHANUMERIC, ^B INDIACTES ANY NON-ALPHANUMERIC ;- CMDSFT: MOV R1,-(SP) ;SAVE R1 MOV R2,-(SP) ;SAVE R2 MOV R4,-(SP) ;SAVE R4 MOV R5,-(SP) ;SAVE R5 TST REPCT ;SEARCH ACROSS PAGES? BGT 3$ ;BR IF NO MOV #ESRPB,R0 ;INDICATE WE ARE SEARCHING CALL DSPMS ;DISPLAY MESSAGE 3$: CLR R5 ;NUMBER OF LINES MOVED DOWN 5$: MOV BFCUR,R4 ;POINT AT CURRENT LINE 10$: MOV R4,R0 ;GET CURRENT LINE BEQ 45$ ;BR IF END OF BUFFER, FAILED CMP (R0)+,(R0)+ ;POINT AT COUNT MOV (R0)+,R1 ;GET THE COUNT, POINT AT DATA ADD BFPOS,R0 ;WHERE TO START SEARCH SUB BFPOS,R1 ;NUMBER CHARS LEFT ON LINE CLR BFPOS ;FOR NEXT LINE 15$: MOV #BFSCH,R2 ;POINT AT SEARCH TEXT BUFFER CMP R1,(R2) ;ENOUGH AT END OF THIS LINE? BLT 43$ ;BR IF NOT ENOUGH CHARS TO MATCH MOV (R2)+,R3 ;GET SEARCH STRING LENGTH BEQ 50$ ;BR IF ZERO, INSTANT MATCH MOV R0,-(SP) ;SAVE CURRENT CHAR ADDRESS MOV R1,-(SP) ;SAVE NUMBER OF CHARS IN LINE 20$: CMPB #2,(R2) ;IS THIS A SPECIAL SEARCH CHAR? BLT 33$ ;BR IF NO CMPB #'0,(R0) ;SEE IF CHARACTER IS AN ALPHANUMERIC BGT 30$ ;BR IF NO CMPB #'9,(R0) ;IS IT IN NUMERIC RANGE? BGE 25$ ;BR IF YES CMPB #'A,(R0) ;NON-ALPHA? BGT 30$ ;BR IF YES CMPB #'Z,(R0) ;ALPHA? BGE 25$ ;BR IF YES CMPB #'A+40,(R0) ;NON-ALPHA? BGT 30$ ;BR IF YES CMPB #'Z+40,(R0) ;NON-ALPHA? BLT 30$ ;BR IF YES 25$: INC R0 ;CHARACTER IS ALPHA CMP #1,(R2)+ ;WERE WE LOOKING FOR ALPHA? BEQ 35$ ;BR IF YES BR 40$ ;BR IF MISMATCH 30$: INC R0 ;CHARACTER IS NON-ALPHA CMP #2,(R2)+ ;WERE WE LOOKING FOR NON-ALPHA? BEQ 35$ ;BR IF YES BR 40$ ;BR IF MISMATCH 33$: CMPB (R0)+,(R2)+ ;DO CHARS MATCH? BNE 40$ ;BR IF NO 35$: DEC R3 ;DID ALL OF THEM MATCH? BGT 20$ ;BR IF NOT YET DEC REPCT ;FOUND MATCH, WAS ONE ENOUGH? BGT 40$ ;BR IF NO, FIND NEXT CMP (SP)+,(SP)+ ;CLEAN STACK BR 50$ ;GO REFRESH SCREEN 40$: MOV (SP)+,R1 ;NO MATCH YET, RECOVER COUNT MOV (SP)+,R0 ;RECOVER CHARACTER ADDRESS INC R0 ;TRY AT NEXT CHARACTER DEC R1 ;END OF LINE IS SHRINKING BGT 15$ ;TRY AGAIN 43$: MOV (R4),R4 ;NO MATCH ON THIS LINE, TRY NEXT TST R5 ;STILL ON OLD PAGE? BMI 10$ ;BR IF NO INC R5 ;ONE MORE LINE FURTHER DOWN BR 10$ ;TRY THIS LINE 45$: TST REPCT ;NO MATCH ON THIS PAGE, CROSS PAGES? BGT 48$ ;BR IF NO, SEARCH FAILED MOV #-1,R5 ;NO LONGER ON SAME PAGE CALL WTPAG ;WRITE OUT THE PAGE BCS 48$ ;BR IF NO FILE OPEN MOV #1,R0 ;NO MESSAGES CALL RDPAG ;READ IN NEW PAGE BCC 5$ ;BR IF CAN TRY AGAIN ON NEW PAGE 48$: CLR R0 ;SEARCH FAILURE (CAN'T MOVE CURSOR) MOV #-1,-(SP) ;INDICATE FAILURE BR 53$ 50$: CLR -(SP) ;SEARCH SUCCESS 53$: CALL CLRBT ;CLEAR BOTTOM LINE MOV #SC.CUR,R2 ;GO BACK TO NORMAL LINE ON SCREEN CALL DSPPS ;SO OTHER ROUTINES WILL WORK PROPERLY MOV R0,R1 ;SAVE ADDRESS OF CURRENT CHAR MOV R5,REPCT ;SET COUNT FOR MOVING DOWN LINES BLE 55$ ;BR IF WE DONT HAVE TO CALL CMDBNL ;MOVE DOWN SOME LINES SUB BFCUR,R1 ;SHOULD BE IN SAME LINE (I HOPE) SUB #6,R1 ;GET OFFSET TO CURRENT CHARACTER BLE 60$ ;BR IF START OF LINE OR ERROR MOV R1,REPCT ;SET THE REPEAT COUNT MOV R0,R1 ;SAVE SCREEN DISPLAY ARG (FROM CMDBNL) CALL CMDMCR ;MOVE THE CURSOR OVER MOV R1,R0 ;RESTORE SCREEN DISPLAY ARGUMENT BR 60$ ;FINISHED 55$: MOV R4,BFCUR ;RESET THE CURRENT LINE CALL CMDBOL ;SET TO THE BEGINNING OF THE LINE SUB R4,R1 ;SHOULD BE IN SAME LINE SUB #6,R1 ;OFFSET TO CURRENT CHARACTER BLE 58$ ;BR IF START OF LINE OR ERROR MOV R1,REPCT ;SET THE REPEAT COUNT CALL CMDMCR ;MOVE CURSOR TO RIGHT CHARACTER 58$: CLR R0 ;NO CHANGE ON SCREEN TST R5 ;ON SAME LINE AS BEFORE? BEQ 60$ ;BR IF YES MOV #1,R0 ;CHANGE ENTIRE SCREEN 60$: TST (SP)+ ;SUCCESS OR FAILURE? BEQ 65$ ;BR IF SUCCESS MOV R0,R2 ;SAVE THE DISPLAY ARGUMENT MOV #ESRFB,R0 ;INDICATE SEARCH FAILURE CALL DSPMS ;TELL USER MOV R2,R0 ;RESTORE DISPLAY ARGUMENT MOV #SC.CUR,R2 ;SET TO CURRENT LINE CALL DSPPS ;RESET CURSOR 65$: MOV (SP)+,R5 ;RESTORE R5 MOV (SP)+,R4 ;RESTORE R4 MOV (SP)+,R2 ;RESTORE R2 MOV (SP)+,R1 ;RESTORE R1 RETURN .SBTTL CMD - REPLACE WITH TEXT ;+ ; -CMDRWT- REPLACE SEARCHED FOR TEXT WITH REPLACEMENT TEXT ;- CMDRWT: MOV R2,-(SP) ;SAVE R2 MOV R4,-(SP) ;SAVE R4 MOV R5,-(SP) ;SAVE R5 CLR R0 ;ASSUME NO SCREEN CHANGE BIT #FL.LCS,FLAGS ;DID WE JUST SEARCH? BEQ 30$ ;BR IF NO, CAN'T REPLACE SEARCH TEXT TST BFCUR ;DO WE HAVE A CURRENT BUFFER? BEQ 30$ ;BR IF NO, SEARCH FAILED MOV BFSCH,REPCT ;SET REPEAT COUNT WITH SEARCH LENGTH BEQ 10$ ;BR IF NOTHING CALL CMDDPC ;DELETE SOME CHARACTERS 10$: MOV #BFREP,R4 ;POINT AT REPLACE TEXT BUFFER MOV (R4)+,R5 ;GET THE COUNT FOR CHARACTER INSERTION BEQ 30$ ;BR IF NONE 15$: MOV #1,REPCT ;REPEAT COUNT OF ONE MOVB (R4)+,R0 ;GET THE CHARACTER CALL CMDINS ;GO INSERT IT DEC R5 ;COUNT DOWN BGT 15$ ;BR IF MORE CHARACTERS 30$: MOV (SP)+,R5 ;RESTORE R5 MOV (SP)+,R4 ;RESTORE R4 MOV (SP)+,R2 ;RESTORE R2 MOV #3,R0 ;UPDATE END OF LINE ON SCREEN RETURN .SBTTL CMD - INSERT NEW LINE ;+ ; -CMDINL- INSERT NEW LINE AT CURSOR POSITION ;- CMDINL: MOV R1,-(SP) ;SAVE R1 MOV R2,-(SP) ;SAVE R2 MOV R4,-(SP) ;SAVE R4 MOV R5,-(SP) ;SAVE R5 CALL GETBF ;GET A LINE BUFFER BCS 50$ ;BR IF CAN'T MOV BFCUR,R5 ;POINT AT THE CURRENT LINE BNE 20$ ;BR IF ONE EXISTS CLR (R0) ;NO FORWARD LINK (END OF LIST) MOV BFBOT,2(R0) ;SET BACKWARD LINK BEQ 10$ ;BR IF NO PREVIOUS LINE MOV R0,@2(R0) ;SET FORWARD LINK FOR PREVIOUS BR 15$ 10$: MOV R0,BFTOP ;SET FORWARD LINK FOR TOP POINTER 15$: MOV R0,BFBOT ;SET NEW BOTTOM LINE CLR 4(R0) ;ZERO BYTE COUNT BR 45$ ;DONE 20$: MOV R0,BFCUR ;MAKE THIS THE CURRENT LINE MOV R5,2(R0) ;SET BACKWARD LINK MOV (R5),(R0) ;SET FORWARD LINK BNE 25$ ;BR IF NOT NEW BOTTOM LINE MOV R0,BFBOT ;MAKE THIS THE NEW BOTTOM LINE BR 30$ 25$: MOV (R0),R1 ;POINT AT NEXT LINE BUFFER MOV R0,2(R1) ;SET ITS BACK POINTER 30$: MOV R0,(R5) ;SET FORWARD POINTER FOR PREVIOUS CLR 4(R0) ;NULL BYTE COUNT (SO FAR) MOV BFPOS,R2 ;GET POSITON IN OLD LINE CMP R2,4(R5) ;AT END OF LINE? BEQ 40$ ;BR IF YES, NOTHING TO MOVE CMP (R5)+,(R5)+ ;POINT AT BYTE COUNT IN OLD MOV (R5),-(SP) ;SAVE OLD BYTE COUNT MOV R2,(R5)+ ;SET BYTE COUNT TO LINE POSITION ADD R2,R5 ;POINT AT CHARACTERS TO MOVE OUT SUB R2,(SP) ;NUMBER OF CHARACTERS TO MOVE MOV (SP)+,R2 ;GET THE NUMBER TO MOVE ADD #4,R0 ;POINT AT DATA COUNT IN NEW LINE MOV R2,(R0)+ ;SET DATA COUNT 35$: MOVB (R5)+,(R0)+ ;MOVE POST-CURSOR BYTES INTO NEW DEC R2 ;COUNT CHARACTERS BGT 35$ ;BR IF MORE 40$: CLR BFPOS ;POSITION IS AT BEGINNING CLR R3 ;ALSO AT BEGINNING OF LINE 45$: CALL CLRLN ;CLEAR THE END OF THE LINE CALL SCRUP ;SCROLL SCREEN UP MOV #SC.CUR,R2 ;POSITION AT NORMAL LINE CALL DSPPS ;MOVE TO POSITION MOV #2,R0 ;SET TO DISPLAY BOTTOM OF BUFFER BR 60$ 50$: MOV #NBUFB,R0 ;NO LINES AVAILABLE CALL DSPMS MOV #SC.CUR,R2 CALL DSPPS CLR R0 ;NO DISPLAY CHANGE 60$: MOV (SP)+,R5 ;RESTORE R5 MOV (SP)+,R4 ;RESTORE R4 MOV (SP)+,R2 ;RESTORE R2 MOV (SP)+,R1 ;RESTORE R1 RETURN .SBTTL CMD - OPEN NEW LINE ;+ ; -CMDONL- OPEN NEW LINE AT CURSOR POSITION ;- CMDONL: MOV R1,-(SP) ;SAVE R1 MOV R2,-(SP) ;SAVE R2 MOV R4,-(SP) ;SAVE R4 MOV R5,-(SP) ;SAVE R5 CALL GETBF ;GET A LINE BUFFER BCS 50$ ;BR IF CAN'T MOV BFCUR,R5 ;POINT AT THE CURRENT LINE BNE 20$ ;BR IF ONE EXISTS MOV R0,BFCUR ;MAKE THIS THE CURRENT LINE CLR (R0) ;NO FORWARD LINK (END OF LIST) MOV BFBOT,2(R0) ;SET BACKWARD LINK BEQ 10$ ;BR IF NO PREVIOUS LINE MOV R0,@2(R0) ;SET FORWARD LINK FOR PREVIOUS BR 15$ 10$: MOV R0,BFTOP ;SET FORWARD LINK FOR TOP POINTER 15$: MOV R0,BFBOT ;SET NEW BOTTOM LINE CLR 4(R0) ;ZERO BYTE COUNT BR 45$ ;DONE 20$: MOV R0,BFCUR ;MAKE THIS THE CURRENT LINE MOV R5,(R0) ;SET FORWARD LINK MOV 2(R5),2(R0) ;SET BACKWARD LINK BNE 25$ ;BR IF NOT NEW TOP LINE MOV R0,BFTOP ;MAKE THIS THE NEW TOP LINE BR 30$ 25$: MOV R0,@2(R0) ;SET FORWARD POINTER FOR PREVIOUS 30$: MOV R0,2(R5) ;SET BACKWARD POINTER FOR NEXT CLR 4(R0) ;NULL BYTE COUNT (SO FAR) MOV BFPOS,R2 ;GET POSITON IN OLD LINE BEQ 45$ ;IF AT BEGINNING, NOTHING TO MOVE MOV R0,R4 ;COPY LINE BUFFER ADDRESS CMP (R4)+,(R4)+ ;POINT AT BYTE COUNT MOV R2,(R4)+ ;SET BYTE COUNT TO LINE POSITION ADD #6,R5 ;POINT AT DATA IN OLD LINE MOV R5,R1 ;COPY POINTER 35$: MOVB (R1)+,(R4)+ ;MOVE PRE-CURSOR BYTES INTO NEW DEC R2 ;COUNT CHARACTERS BGT 35$ ;BR IF MORE MOV -(R5),R2 ;GET TOTAL NUMBER OF BYTES IN OLD SUB BFPOS,R2 ;GET WHATS LEFT MOV R2,(R5)+ ;SET BYTE COUNT 40$: MOVB (R1)+,(R5)+ ;MOVE DOWN TO START OF LINE DEC R2 ;COUNT CHARACTERS BGT 40$ ;BR IF MORE 45$: MOV #2,R0 ;SET TO DISPLAY END OF BUFFER BR 60$ 50$: MOV #NBUFB,R0 ;NO LINES AVAILABLE CALL DSPMS MOV #SC.CUR,R2 CALL DSPPS CLR R0 ;NO DISPLAY CHANGE 60$: MOV (SP)+,R5 ;RESTORE R5 MOV (SP)+,R4 ;RESTORE R4 MOV (SP)+,R2 ;RESTORE R2 MOV (SP)+,R1 ;RESTORE R1 RETURN .SBTTL CMD - MOVE CURSOR UP, DOWN ;+ ; -CMDMCU- MOVE CURSOR UP ; -CMDMCD- MOVE CURSOR DOWN ;- CMDMCU: NEG REPCT ;INDICATE TO MOVE UP CMDMCD: MOV R1,-(SP) ;SAVE R1 MOV R2,-(SP) ;SAVE R2 MOV R4,-(SP) ;SAVE R4 CMP R3,MCLRP ;SAME POSITION AS LAST TIME? BEQ 5$ ;BR IF YES, USE SAME ORIGINAL POSITION MOV R3,MCORP ;RESET ORIGINAL POSITION 5$: CLR -(SP) ;DISPLAY OUTPUT, ASSUME NO CHANGE TST REPCT ;MOVE UP OR DOWN? BEQ 40$ ;BR IF MOVE NOWHERE BMI 10$ ;BR IF MOVE UP CALL CMDBNL ;MOVE DOWN SOME LINES BR 15$ ;AND SKIP NEXT 10$: NEG REPCT ;MAKE COUNT POSITIVE CALL CMDBPL ;MOVE UP SOME LINES 15$: MOV R0,(SP) ;SAVE THE DISPLAY CHANGE TYPE MOV BFCUR,R0 ;POINT AT CURRENT LINE BEQ 40$ ;BR IF NONE CMP (R0)+,(R0)+ ;POINT AT BYTE COUNT MOV (R0)+,R4 ;GET BYTE COUNT, POINT AT CHARS BEQ 40$ ;BR IF NONE CLR R1 ;NO TRANSLATION BUFFER CLR -(SP) ;USE AS A CHARACTER COUNTER 20$: MOV R3,R2 ;SAVE THIS POSITION CALL TRNCR ;GET NEXT POSITION INC (SP) ;GONE PAST ANOTHER CHARACTER CMP R3,MCORP ;HOW DOES IT COMPARE WITH LAST LINES? BEQ 30$ ;BR IF PERFECTLY BGT 25$ ;BR IF TOO HIGH DEC R4 ;COUNT CHARS IN LINE BGT 20$ ;BR IF MORE BR 30$ ;USE LAST POSITION 25$: MOV R2,R3 ;USE PREVIOUS POSITION DEC (SP) ;BACK UP ONE CHARACTER 30$: MOV (SP)+,BFPOS ;RESET THE POSITION CMP (SP),#1 ;WILL DISPLAY CHANGE POSITION CURSOR? BEQ 40$ ;BR IF YES CMP (SP),#2 ;MAKE SURE IT WON'T BEQ 40$ ;BR IF IT WILL TST R3 ;DO WE HAVE TO MOVE ANYWAY? BEQ 40$ ;BR IF NO MOV #30,R2 ;STAY ON SAME LINE CALL DSPPS ;MOVE THE CURSOR 40$: MOV R3,MCLRP ;SET NEW "LAST POSITION MOVED TO" MOV (SP)+,R0 ;SET DISPLAY CHANGE SWITCH MOV (SP)+,R4 ;RESTORE R4 MOV (SP)+,R2 ;RESTORE R2 MOV (SP)+,R1 ;RESTORE R1 RETURN .SBTTL CMD - MOVE CURSOR LEFT, RIGHT ;+ ; -CMDMCL- MOVE CURSOR TO LEFT ; -CMDMCR- MOVE CURSOR TO RIGHT ;- CMDMCL: MOV R2,-(SP) ;SAVE R2 TST REPCT ;LEGAL COUNT? BLE 20$ ;BR IF NO, DO IT NO TIMES MOV BFCUR,R0 ;POINT AT CURRENT LINE BUFFER BEQ 20$ ;BR IF NONE, CAN'T MOVE CMP BFPOS,REPCT ;IS REPCT TO BIG? BGE 10$ ;BR IF NO MOV BFPOS,REPCT ;SET IT TO THE MAXIMUM BEQ 20$ ;BR IF NO CHARACTERS AT ALL 10$: CLR R3 ;PRETEND AT LEFT OF SCREEN SUB REPCT,BFPOS ;MOVING TO THIS CHARACTER BEQ 15$ ;BR IF AT LEFT OF SCREEN MOV BFPOS,R2 ;GET NUMBER OF CHARS TO MOVE OVER ADD #6,R0 ;POINT AT CHARACTERS CALL TRNPS ;FIND THE PROPER SCREEN POSITION 15$: MOV #30,R2 ;STAY ON SAME LINE CALL DSPPS ;PLACE CURSOR IN POSITION 20$: MOV (SP)+,R2 ;RECOVER R2 CLR R0 ;NO DISPLAY CHANGE RETURN CMDMCR: MOV R2,-(SP) ;SAVE R2 TST REPCT ;LEGAL COUNT? BLE 20$ ;BR IF NO MOV BFCUR,R0 ;POINT AT CURRENT LINE BEQ 20$ ;BR IF NONE CMP (R0)+,(R0)+ ;POINT AT CHARACTER COUNT MOV (R0)+,R2 ;GET CHARACTER COUNT SUB BFPOS,R2 ;NUMBER OF CHARS AT END OF LINE BEQ 20$ ;BR IF NONE CMP REPCT,R2 ;COUNT TOO BIG? BLE 10$ ;BR IF NO MOV R2,REPCT ;RESET THE COUNT 10$: ADD REPCT,BFPOS ;RESET LINE POSITION MOV BFPOS,R2 ;GET NUMBER OF CHARS TO MOVE OVER CLR R3 ;PLACE AT LEFT OF SCREEN CALL TRNPS ;SET POSITION AFTER LAST CHAR MOV #30,R2 ;STAY ON SAME LINE CALL DSPPS ;POSITION THE CURSOR 20$: MOV (SP)+,R2 ;RECOVER R2 CLR R0 ;NO DISPLAY CHANGE RETURN .SBTTL CMD - APPEND OR PREFACE NEXT LINE ;+ ; -CMDPNL- PREFACE END OF LINE TO NEXT LINE ; -CMDDAL- DELETE END AND APPEND NEXT LINE ; -CMDANL- APPEND NEXT LINE TO END OF CURRENT LINE ;- CMDPNL: CALL CMDINL ;INSERT A NEW LINE HERE CALL CMDANL ;APPEND THE NEXT LINE MOV #2,R0 ;DISPLAY END OF BUFFER RETURN CMDDAL: MOV R5,-(SP) ;SAVE R5 MOV REPCT,R5 ;SAVE THE COUNT 10$: CALL CMDDEL ;DELETE END OF LINE CALL CMDANL ;APPEND NEXT LINE DEC R5 ;HOW MANY TIMES BGT 10$ ;BR IF MORE MOV (SP)+,R5 ;RESTORE R5 MOV #2,R0 ;UPDATE END OF SCREEN RETURN CMDANL: MOV R1,-(SP) ;SAVE R1 MOV R2,-(SP) ;SAVE R2 MOV R4,-(SP) ;SAVE R4 MOV BFCUR,R0 ;POINT AT CURRENT LINE BEQ 40$ ;BR IF NONE, NO APPEND MOV (R0),R1 ;POINT AT NEXT LINE BEQ 27$ ;BR IF NONE, NO APPEND (MAYBE) CMP (R0)+,(R0)+ ;POINT AT CURRENT LINE COUNT CMP (R0),#NM.CHR ;AT END OF LINE ALREADY? BGE 40$ ;BR IF YES, NO APPEND MOV (R0),BFPOS ;SET TO END OF CURRENT LINE CLR R3 ;SET TO LEFT SIDE OF SCREEN MOV (R0)+,R2 ;GET THE COUNT BEQ 5$ ;BR IF AT LEFT OF SCREEN CALL TRNPS ;SET TO NEW POSITION 5$: MOV R0,R2 ;COPY ADDRESS OF LINE ADD -(R2),R0 ;POINT AFTER LAST CHARACTER CMP (R1)+,(R1)+ ;POINT AT COUNT FOR NEXT LINE MOV R1,R4 ;COPY POINTER TO COUNT TST (R1)+ ;POINT AT FIRST CHARACTER ON LINE BEQ 20$ ;BR IF NONE, JUST DELETE LINE 10$: MOVB (R1)+,(R0)+ ;TACK CHARACTERS ON END OF CURRENT INC (R2) ;ONE MORE ON CURRENT LINE DEC (R4) ;ONE LESS CHAR ON NEXT LINE BLE 20$ ;BR IF NO MORE CMP (R2),#NM.CHR ;AT END OF LINE YET? BLT 10$ ;BR IF NO MOV (R4)+,R2 ;GET COUNT OF WHATS LEFT ON NEXT LINE 15$: MOVB (R1)+,(R4)+ ;MOVE IT DOWN DEC R2 ;COUNT CHARACTERS BGT 15$ ;BR IF MORE MOV #2,R0 ;UPDATE END OF SCREEN BR 45$ 20$: CMP -(R2),-(R2) ;POINT AT CURRENT LINE (DELETE NEXT) CMP -(R4),-(R4) ;POINT AT NEXT LINE MOV (R4),R1 ;POINT AT LINE AFTER NEXT BEQ 25$ ;BR IF NONE (BOTTOM OF BUFFER) MOV R2,2(R1) ;REMOVE NEXT LINE FROM LIST MOV R1,(R2) ;BY RELINKING BR 26$ 25$: MOV R2,BFBOT ;RESET BOTTOM POINTER CLR (R2) ;LINK TO BOTTOM 26$: MOV R4,R0 ;GET LINE BUFFER ADDRESS CALL RETBF ;RETURN THE BUFFER MOV #2,R0 ;UPDATE END OF SCREEN BR 45$ 27$: TST 4(R0) ;APPENDING END OF BUFFER BNE 40$ ;BR IF CURRENT LINE NOT EMPTY MOV 2(R0),R1 ;POINT AT PREVIOUS LINE BEQ 28$ ;BR IF NONE CLR (R1) ;CLEAR ITS FORWARD POINTER (NEW EOB) 28$: MOV R1,BFBOT ;RESET THE BOTTOM POINTER BNE 29$ ;BR IF BUFFER NOT EMPTY CLR BFTOP ;NO TOP BUFFER EITHER 29$: CLR BFCUR ;NO CURRENT BUFFER CLR BFPOS ;BEFORE FIRST CHARACTER ON LINE CLR R3 ;AT LEFT OF SCREEN CALL RETBF ;RETURN THE BUFFER MOV #2,R0 ;DISPLAY FROM CURRENT LINE DOWN BR 45$ 40$: CLR R0 ;NO DISPLAY CHANGE 45$: MOV (SP)+,R4 ;RESTORE R4 MOV (SP)+,R2 ;RESTORE R2 MOV (SP)+,R1 ;RESTORE R1 RETURN .SBTTL CMD - TOP, BOTTOM, OR FRAME ;+ ; -CMDTOP- TOP OF PAGE ; -CMDBOP- BOTTOM OF PAGE ; -CMDFRM- MOVE A FRAME ;- CMDTOP: MOV #NM.LIN,REPCT ;FOR ALL LINES CALL CMDBPL ;MOVE TO BEGINNING OF PREVIOUS LINE RETURN CMDBOP: MOV #NM.LIN,REPCT ;FOR ALL LINES CALL CMDBNL ;MOVE TO BEGINNING OF NEXT LINE RETURN CMDFRM: MOV R1,-(SP) ;SAVE R1 CLR R0 ;ASSUME NO SCREEN CHANGE MOV REPCT,R1 ;COPY THE REPEAT COUNT BEQ 25$ ;BR IF NULL CLR REPCT ;MAKE IT NULL FOR NOW MOV R1,-(SP) ;SAVE THE COUNT BGT 10$ ;BR IF POSITIVE NEG R1 ;MAKE IT POSITIVE 10$: ADD #SC.LIN,REPCT ;MOVE THIS MANY TIMES REPEAT COUNT DEC R1 ;COUNT MULTIPLIER BGT 10$ ;BR IF MORE DEC REPCT ;FOR CONTINUITY IF REPCT EQUALED ONE TST (SP)+ ;MOVE UP OR DOWN? BMI 15$ ;MOVE DOWN CALL CMDBNL ;MOVE DOWN SOME LINES BR 25$ 15$: CALL CMDBPL ;MOVE UP SOME LINES 25$: MOV (SP)+,R1 ;RESTORE R1 RETURN .SBTTL CMD - END OF NEXT OR PREVIOUS LINE ;+ ; -CMDENL- MOVE TO END OF NEXT LINE ; -CMDEPL- MOVE TO END OF PREVIOUS LINE ;- .ENABL LSB CMDENL: CALL CMDBNL ;MOVE DOWN SOME LINES BR 10$ CMDEPL: CALL CMDBPL ;MOVE UP SOME LINES 10$: MOV R0,-(SP) ;SAVE DISPLAY ARGUMENT CALL CMDEOL ;MOVE TO THE END MOV (SP)+,R0 ;RESTORE IT RETURN .DSABL LSB .SBTTL CMD - BEGINNING OF NEXT LINE ;+ ; -CMDBNL- MOVE CURSOR TO BEGINNING OF NEXT LINE ; ; ROUTINE MAY SCROLL SCREEN DISPLAY INTERNALLY ;- CMDBNL: MOV R1,-(SP) ;SAVE R1 MOV R2,-(SP) ;SAVE R2 MOV R5,-(SP) ;SAVE R5 CLR R0 ;NO SCREEN CHANGE IF NOWHERE TO GO MOV BFCUR,R5 ;GET CURRENT LINE BUFFER BEQ 60$ ;BR IF NONE, NOWHERE TO GO MOV REPCT,R0 ;LEGAL COUNT? BLE 60$ ;BR IF NO, NO DISPLAY CHANGE CLR R2 ;COUNTER FOR LINES AWAY FROM CURRENT 10$: MOV (R5),R5 ;SET TO POINT TO NEXT LINE BUFFER BEQ 20$ ;BR IF AT END INC R2 ;ONE MORE LINE AWAY FROM CURRENT DEC R0 ;COUNT DOWN BGT 10$ ;BR IF MORE TO GO 20$: CMP R2,#SC.LIN-2 ;TOO MANY TO SCROLL? BLT 30$ ;BR IF NO MOV R5,BFCUR ;RESET THE CURRENT LINE CLR BFPOS ;POSITION AT BEGINNING CLR R3 ;AND AT LEFT OF SCREEN MOV #1,R0 ;SET TO DISPLAY ENTIRE SCREEN FULL BR 60$ ;DONE 30$: MOV BFCUR,R5 ;GET CURRENT BUFFER AGAIN MOV #SC.LIN-SC.CUR,R2 ;GET LAST LINE ON SCREEN 35$: MOV (R5),R5 ;FIND THE LAST LINE ON THE SCREEN BEQ 40$ ;BR IF ITS AN END OF BUFFER MARK DEC R2 ;COUNT DOWN BGT 35$ ;BR IF MORE TO GO 40$: CALL SCRUP ;SCROLL THE SCREEN UP MOV @BFCUR,BFCUR ;SET CURRENT LINE TO NEXT LINE BEQ 55$ ;BR IF AT END OF BUFFER MARK TST R5 ;ANY NEW LINE TO DISPLAY? BEQ 50$ ;BR IF NO MOV (R5),R5 ;POINT AT NEXT "LAST LINE" BNE 45$ ;BR IF ANYTHING TO DISPLAY MOV #'A,R0 ;SET TO MOVE UP A LINE CALL DSPES ;MOVE UP TO "LAST LINE" CALL DSPBL ;DISPLAY BLOCK CHARACTER BR 50$ ;AND FINISHED WITH DISPAY 45$: MOV R5,R0 ;POINT AT LINE TO DISPLAY CMP (R0)+,(R0)+ ;POINT AT CHARACTER COUNT MOV (R0)+,R1 ;SET THE COUNT, POINT AT CHARACTERS MOV #SC.LIN,R2 ;SET TO LAST DISPLAY LINE CLR R3 ;AND LEFT OF SCREEN CALL DSPLN ;DISPLAY THE LINE 50$: DEC REPCT ;ONE LESS LINE TO GO BGT 40$ ;BR IF MORE 55$: MOV #SC.CUR,R2 ;SET TO NORMAL CURSOR LINE CLR R3 ;FAR LEFT OF SCREEN CLR BFPOS ;POSITION AT BEGINNING OF LINE CALL DSPPS ;PLACE THE CURSOR ON THE SCREEN CLR R0 ;DISPLAY WAS HANDLED INTERNALLY 60$: MOV (SP)+,R5 ;RECOVER R5 MOV (SP)+,R2 ;RECOVER R2 MOV (SP)+,R1 ;RECOVER R1 RETURN .SBTTL CMD - BEGINNING OF PREVIOUS LINE ;+ ; -CMDBPL- MOVE CURSOR TO BEGINNING OF PREVIOUS LINE ; ; SCREEN DISPLAY MAY BE SCROLLED INTERNALLY ;- CMDBPL: MOV R1,-(SP) ;SAVE R1 MOV R2,-(SP) ;SAVE R2 MOV R5,-(SP) ;SAVE R5 CALL CMDBOL ;IN CASE ITS ALREADY AT THE TOP MOV REPCT,R0 ;LEGAL COUNT? BLE 60$ ;BR IF NO, NO SCREEN CHANGE MOV BFCUR,R5 ;GET CURRENT LINE BUFFER CLR R0 ;IF AT TOP, NO DISPLAY CHANGE CMP R5,BFTOP ;ALEADY AT TOP? BEQ 60$ ;BR IF YES, CANNOT MOVE UP CLR R0 ;NUMBER OF LINES AWAY FROM CURRENT MOV REPCT,R1 ;CPY REPEAT COUNT TST R5 ;AT END OF BUFFER? BNE 10$ ;BR IF NO MOV BFBOT,R5 ;POINT AT NEXT TO LAST LINE BEQ 60$ ;IF NO TOP LINE, NOTHING TO DO BR 15$ ;CONTINUE 10$: MOV 2(R5),R5 ;POINT TO PREVIOUS LINE BEQ 20$ ;BR IF AT TOP OF BUFFER 15$: INC R0 ;ONE MORE LINE DISTANT DEC R1 ;COUNT DOWN BGT 10$ ;BR IF MORE TO GO 20$: CMP R0,#SC.LIN-2 ;TOO MANY LINES TO SCROLL? BLT 30$ ;BR IF NO MOV R5,BFCUR ;RESET THE CURRENT LINE BNE 25$ ;BR IF GOT ONE MOV BFTOP,BFCUR ;SET TO TOP LINE 25$: CLR BFPOS ;POSITION AT BEGINNING CLR R3 ;AND AT LEFT OF SCREEN MOV #1,R0 ;DISPLAY ENTIRE SREEN BR 60$ ;DONE 30$: MOV BFCUR,R5 ;GT CURRENT BUFFER AGAIN MOV #SC.CUR,R2 ;THIS MANY UP FOR FIRST ON SCREEN TST R5 ;AT BOTTOM OF BUFFER? BNE 35$ ;BR IF NO MOV BFBOT,R5 ;GO TO PREVIOUS LINE BR 38$ ;SKIP NEXT 35$: MOV 2(R5),R5 ;FIND THE FIRST LINE ON THE SCREEN BEQ 40$ ;BR IF ITS A START OF BUFFER MARK 38$: DEC R2 ;COUNT DOWN BGT 35$ ;BR IF MORE TO GO 40$: MOV BFCUR,R0 ;POINT AT CURRENT LINE BNE 43$ ;BR IF THERE IS A CURRENT LINE MOV BFBOT,R0 ;SET TO BOTTOM LINE BR 44$ ;SKIP NEXT 43$: MOV 2(R0),R0 ;SET CURRENT LINE TO PREVIOUS LINE BEQ 55$ ;BR IF AT START OF BUFFER MARK 44$: MOV R0,BFCUR ;SET THE NEW CURRENT LINE CALL SCRDN ;SCROLL THE SCREEN DOWN TST R5 ;ANY NEW LINE TO DISPLAY? BEQ 50$ ;BR IF NO MOV 2(R5),R5 ;POINT AT NEXT "FIRST LINE" BNE 45$ ;BR IF ANYTHING TO DISPLAY CALL DSPBL ;DISPLAY BLOCK CHARACTER BR 50$ ;AND FINISHED WITH DISPAY 45$: MOV R5,R0 ;POINT AT LINE TO DISPLAY CMP (R0)+,(R0)+ ;POINT AT CHARACTER COUNT MOV (R0)+,R1 ;SET THE COUNT, POINT AT CHARACTERS MOV #30,R2 ;STAY ON TOP LINE CLR R3 ;AND LEFT OF SCREEN CALL DSPLN ;DISPLAY THE LINE 50$: DEC REPCT ;ONE LESS LINE TO GO BGT 40$ ;BR IF MORE 55$: MOV #SC.CUR,R2 ;SET TO NORMAL CURSOR LINE CLR R3 ;FAR LEFT OF SCREEN CLR BFPOS ;POSITION AT BEGINNING OF LINE CALL DSPPS ;PLACE THE CURSOR ON THE SCREEN CLR R0 ;DISPLAY CHANGE HANDLED INTERNALLY 60$: MOV (SP)+,R5 ;RECOVER R5 MOV (SP)+,R2 ;RECOVER R2 MOV (SP)+,R1 ;RECOVER R1 RETURN .SBTTL CMD - BEGINNING AND END OF CURRENT LINE ;+ ; -CMDBOL- MOVE CURSOR TO BEGINNING OF LINE ; -CMDEOL- MOVE CURSOR TO END OF LINE ;- .ENABL LSB CMDBOL: MOV R2,-(SP) ;SAVE R2 CLR BFPOS ;SET POSITION TO BEGINNING CLR R3 ;SET TO LEFT OF SCREEN BR 30$ CMDEOL: MOV R2,-(SP) ;SAVE R2 MOV BFCUR,R2 ;POINT AT CURRENT LINE BEQ 40$ ;BR IF NONE MOV R0,-(SP) ;SAVE R0 MOV R2,R0 ;POINT AT LINE CMP (R0)+,(R0)+ ;POINT AT CHAR COUNT CLR R3 ;START AT LEFT MOV (R0)+,R2 ;GET COUNT, POINT AT CHARS MOV R2,BFPOS ;RESET LINE POSITION BEQ 20$ ;BR IF NONE, USE ZERO POSITION CALL TRNPS ;SET THE SCREEN POSITION 20$: MOV (SP)+,R0 ;RECOVER R0 30$: MOV #30,R2 ;SAME LINE CALL DSPPS ;SET POSITION 40$: MOV (SP)+,R2 ;RECOVER R2 CLR R0 ;NO DISPLAY CHANGE RETURN .DSABL LSB .SBTTL CMD - DELETE START OR END OF LINE ;+ ; -CMDDSL- DELETE THE START OF THE LINE ; -CMDDEL- DELETE THE END OF THE LINE ;- CMDDSL: MOV BFPOS,REPCT ;SET COUNT TO ALL CHARS BEFORE CURSOR CALL CMDDPC ;DELETE THE CHARACTERS RETURN CMDDEL: MOV #NM.CHR,REPCT ;SET THE COUNT (AS MANY AS POSSIBLE) CALL CMDDCC ;DELETE THE CHARACTERS RETURN .SBTTL CMD - DELETE CURRENT CHARACTER ;+ ; -CMDDCC- DELETE CHARACTER ABOVE (IN FRONT OF) CURSOR ;- CMDDCC: MOV R1,-(SP) ;SAVE R1 MOV R2,-(SP) ;SAVE R2 CLR R0 ;IN CASE NOTHING TO DELETE MOV BFCUR,R2 ;POINT AT CURRENT LINE BEQ 30$ ;BR IF NONE, CANT DELETE CMP (R2)+,(R2)+ ;POINT AT CHARACTER COUNT MOV (R2),R1 ;GET THE COUNT SUB BFPOS,R1 ;GET NUMBER OF CHARACTERS DELETABLE BEQ 30$ ;BR IF NONE CMP REPCT,R1 ;TRYING TO DELETE TOO MANY? BLE 10$ ;BR IF NO MOV R1,REPCT ;DELETE ALL THEN 10$: SUB REPCT,R1 ;GET NUMBER OF CHARACTERS LEFT MOV BFPOS,(R2) ;SET CHAR COUNT TO POINTER ADD R1,(R2)+ ;CHANGE TO NUMBER AFTER DELETION TST R1 ;ANYTHING AFTER POINTER? BEQ 25$ ;BR IF NO, JUST KILL REST OF LINE ADD BFPOS,R2 ;POINT AT CHARS TO DELETE MOV R2,R0 ;SAVE THIS POINTER ADD REPCT,R2 ;POINT AT CHARS TO BE MOVED DOWN 15$: MOVB (R2)+,(R0)+ ;MOVE LAST CHARS DOWN OVER DELETED DEC R1 ;MOVED LAST "LAST CHAR"? BGT 15$ ;BR IF NO 25$: MOV #3,R0 ;DISPLAY NEW END OF LINE 30$: MOV (SP)+,R2 ;RESTORE R2 MOV (SP)+,R1 ;RESTORE R1 RETURN .SBTTL CMD - DELETE PREVIOUS CHARACTER ;+ ; -CMDDPC- DELETE CHARACTERS PREVIOUS TO CURSOR ;- CMDDPC: MOV R1,-(SP) ;SAVE R1 MOV R2,-(SP) ;SAVE R2 MOV R4,-(SP) ;SAVE R4 CLR R0 ;IN CASE NOTHING TO DELETE MOV BFCUR,R2 ;POINT AT CURRENT LINE BEQ 30$ ;BR IF NONE, NO SCREEN CHANGE TST BFPOS ;AT BEGINNING OF LINE? BEQ 30$ ;BR IF YES, NO SCREEN CHANGE CMP (R2)+,(R2)+ ;POINT AT CHARACTER COUNT CMP REPCT,BFPOS ;DELETING TOO MANY CHARACTERS? BLE 10$ ;BR IF NO MOV BFPOS,REPCT ;SET TO DELETE MAXIMUM POSSIBLE 10$: MOV BFPOS,R0 ;POINT AFTER CHARS TO DELETE SUB REPCT,BFPOS ;RESET THE CURRENT CHAR POINTER SUB REPCT,(R2) ;ALSO LESS CHARS ON LINE BEQ 18$ ;BR IF NOW NONE MOV (R2)+,R1 ;COUNT OF CHARS AFTER DELETION MOV R2,R4 ;COPY POINTER TO LINE ADD R2,R0 ;POINT AFTER DELETED CHARS ADD BFPOS,R2 ;POINT AT DELETED CHARS SUB BFPOS,R1 ;CHARS AFTER DELETE POSITION BEQ 17$ ;BR IF NOTHING TO MOVE 15$: MOVB (R0)+,(R2)+ ;OVERWRITE DELETED CHARACTERS DEC R1 ;WITH NEW "LAST CHARS ON LINE" BGT 15$ ;BR IF MORE 17$: MOV R4,R0 ;RESTORE LINE POINTER 18$: CLR R3 ;SET TO LEFT OF SCREEN MOV BFPOS,R2 ;COUNT OF CHARS UP TO DELETION BEQ 19$ ;BR IF NONE, STAY ON LEFT CALL TRNPS ;FIND POSITION ON SCREEN 19$: MOV #30,R2 ;STAY ON SAME LINE CALL DSPPS ;MOVE CURSOR TO PROPER POSITION 20$: MOV #3,R0 ;DISPLAY END OF LINE 30$: MOV (SP)+,R4 ;RESTORE R4 MOV (SP)+,R2 ;RESTORE R2 MOV (SP)+,R1 ;RESTORE R1 RETURN .SBTTL SUBRTN - READ PAGE FROM FILE ;+ ; -RDPAG- READ A PAGE OF TEXT INTO THE INPUT BUFFER ; ; INPUTS: ; R0 EQUAL TO ZERO INDICATES GIVE EOF AND BUFFER FULL MESSAGES ; R0 NOT EQUAL TO ZERO INDICATES MESSAGES ARE TO BE SUPPRESSED ; FL.PAG AND FL.EOF IN FLAGS ARE SET PROPERLY ; ; OUTPUTS: ; IF CARRY IS CLEAR, NEW PAGE IS READ IN ; IF CARRY IS SET, THERE IS NO NEW PAGE IN THE BUFFER ; IF FL.PAG IS SET, BUFFER CONTAINS A PAGE MARK ; IF FL.EOF IS SET, THE END OF FILE WAS DETECTED ; NOTE: IF NO INPUT FILE IS OPEN, ROUTINE IS A TOTAL NO-OP ;- RDPAG: SEC ;ASSUME NOTHING READ IN BIT #FL.IFO,FLAGS ;IS AN INPUT FILE OPEN? BEQ 60$ ;BR IF NO, EXIT W/ CARRY SET MOV R1,-(SP) ;SAVE R1 MOV R2,-(SP) ;SAVE R2 MOV R0,-(SP) ;SAVE R0 (MUST BE LAST ON STACK) CLR R2 ;TO HOLD NUMBER OF LINES READ IN BIT #FL.EOF,FLAGS ;IS THE FILE AT EOF? BNE 35$ ;BR IF YES, NO NEW PAGE BIC #FL.PAG,FLAGS ;INDICATE NO PAGE MARK AT END 10$: CMP BFALL,#NM.FIL ;TOO MANY LINES READ IN ALREADY? BGE 40$ ;BR IF YES MOV #INPFDB,R0 ;SET THE INPUT FILE FDB ADDRESS CALL GETLN ;GET A LINE BCS 30$ ;BR IF COULDN'T INC R2 ;ANOTHER NEW LINE MOV BFBOT,2(R0) ;LINK NEW LINE AT BOTTOM OF BUFFER BNE 15$ ;BR IF ITS NOW AT THE BOTTOM MOV R0,BFTOP ;NEW LINE IS AT THE TOP BR 18$ ;SKIP NEXT 15$: MOV R0,@2(R0) ;SET FORWARD LINK FOR OLD BOTTOM TST BFCUR ;WAS OLD CURRENT LINE AT BOTTOM? BNE 20$ ;BR IF NO, LEAVE IT ALONE 18$: MOV R0,BFCUR ;MAKE NEW LINE THE CURRENT LINE CLR BFPOS ;AT BEGINNING OF LINE CLR R3 ;AT LEFT OF SCREEN 20$: CLR (R0) ;CLEAR THE FORWARD LINK MOV R0,BFBOT ;SET THE BOTTOM MARKER CMP (R0)+,(R0)+ ;MOVE TO BYTE COUNT MOV (R0)+,R1 ;GET THE BYTE COUNT BEQ 10$ ;BR IF NO DATA PRESENT 25$: CMPB #14,(R0)+ ;IS THERE A PAGE MARK (FORM-FEED)? BEQ 28$ ;BR IF YES DEC R1 ;COUNT CHARACTERS BGT 25$ ;BR IF MORE BR 10$ ;GO GET NEXT LINE 28$: BIS #FL.PAG,FLAGS ;STOP READING, INDICATE END OF PAGE BR 40$ ;FINISHED 30$: TST R0 ;NO BUFFER OR EOF? BEQ 40$ ;BR IF NO BUFFER (HUH?) BIS #FL.EOF,FLAGS ;INDICATE EOF FOUND 35$: TST R2 ;CLEAR CARRY, ANYTHING READ IN? BNE 45$ ;BR IF YES SEC ;NO NEW PAGE BR 45$ 40$: CLC ;GOT NEW STUFF 45$: ROR R2 ;SAVE THE CARRY TST (SP) ;GIVE MESSAGES? BNE 55$ ;BR IF NO BIT #FL.EOF+FL.PAG,FLAGS ;END OF BUFFER BEFORE END OF PAGE? BNE 50$ ;BR IF NO MOV #EFILB,R0 ;TELL USER CALL DSPMS ;DISPLAY MESSAGE BR 55$ 50$: BIT #FL.EOF,FLAGS ;END OF INPUT FILE? BEQ 55$ ;BR IF NO MOV #EEOFB,R0 ;INDICATE TO USER CALL DSPMS ;DISPLAY MESSAGE 55$: ROL R2 ;RESTORE CARRY MOV (SP)+,R0 ;RESTORE R0 MOV (SP)+,R2 ;RESTORE R2 MOV (SP)+,R1 ;RESTORE R1 60$: RETURN .SBTTL SUBRTN - WRITE CURRENT PAGE TO OUTPUT FILE ;+ ; -WTPAG- WRITE ALL LINES IN BUFFER TO OUTPUT FILE ; ; INPUTS: ; NONE ; ; OUTPUTS: ; IF CARRY IS CLEAR, CONTENTS OF BUFFER ARE WRITTEN TO OUTPUT FILE ; IF CARRY IS SET, THERE IS NO OUTPUT FILE, BUFFER IS NOT CLEARED ;- WTPAG: MOV R0,-(SP) ;SAVE R0 BIT #FL.OFO,FLAGS ;IS AN OUTPUT FILE OPEN? BEQ 20$ ;BR IF NO 10$: MOV BFTOP,R0 ;GET TOP LINE BEQ 15$ ;BR IF NONE MOV (R0),BFTOP ;REMOVE IT CALL PUTLN ;PUT IT IN THE FILE BR 10$ ;DO IT AGAIN 15$: CLR BFBOT ;NO MORE BOTTOM LINE CLR BFCUR ;NO MORE CURRENT LINE CLR BFPOS ;POSITION IS AT LEFT CLR R3 ;AND FAR LEFT OF SCREEN BIC #FL.PAG,FLAGS ;NO PAGE MARKER IN BUFFER CLC ;BUFFER IS WRITTEN BR 25$ ;FINISHED 20$: SEC ;BUFFER IS NOT WRITTEN 25$: MOV (SP)+,R0 ;RESTORE R0 RETURN .SBTTL SUBRTN - GET LINE FROM FILE ;+ ; -GETLN- GET A LINE FROM THE INPUT FILE ; ; INPUTS: ; R0 = FDB ADDRESS FOR INPUT FILE ; ; OUTPUTS: ; CARRY SET INDICATES ERROR ; R0 = 0 IF NO BUFFER FOR DATA ; R0 = -1 IF END OF FILE DETECTED ; CARRY CLEAR INDICATES SUCCESS ; R0 = ADDRESS OF BUFFER ; 4(R0) CONTAINS BYTE COUNT ; 6(R0) STARTS DATA ;- GETLN: MOV R2,-(SP) ;SAVE R2 MOV R0,-(SP) ;SAVE THE FDB ADDRESS CALL GETBF ;GET A LINE BUFFER BCS 10$ ;BR IF CANNOT MOV R0,R2 ;SAVE ADDRESS IN R2 MOV (SP),R0 ;RESTORE THE FDB ADDRESS MOV R2,-(SP) ;SAVE LINE BUFFER ADDRESS ADD #6,R2 ;POINT AT DATA SECTION GET$ R0,R2,#NM.CHR ;GET DATA FROM THE FILE MOV (SP)+,R0 ;RECOVER THE BUFFER ADDRESS MOV (SP)+,R2 ;RECOVER THE FDB ADDRESS BCC 5$ ;BR IF NO ERROR CALL RETBF ;RETURN THE BUFFER CMPB F.ERR(R2),#IE.EOF ;END OF FILE? BEQ 3$ ;BR IF YES MOV #GETERB,R0 ;READ ERROR CALL DSPMS ;DISPLAY THE MESSAGE 3$: MOV #-1,R0 ;END OF FILE SEC ;ERROR BR 30$ 5$: MOV F.NRBD(R2),4(R0) ;SET THE DATA COUNT BR 30$ ;FINISHED 10$: MOV (SP)+,R0 ;CLEAN STACK (SAVE CARRY) MOV #0,R0 ;NO LINE BUFFER (SAVE CARRY) 30$: MOV (SP)+,R2 ;RESTORE R2 RETURN .SBTTL SUBRTN - PUT LINE IN FILE ;+ ; -PUTLN- PUT A LINE IN THE OUTPUT FILE ; ; INPUTS: ; R0 = ADDRESS OF LINE BUFFER ; 4(R0) CONTAINS BYTE COUNT ; 6(R0) STARTS DATA ; ; OUTPUTS: ; DATA IS OUTPUT TO FILE ; LINE BUFFER IS RETURNED TO FREE POOL ;- PUTLN: MOV R2,-(SP) ;SAVE R2 MOV R0,R2 ;SAVE ADDRESS IN R2 MOV R0,-(SP) ;ALSO SAVE ON STACK ADD #6,R2 ;POINT AT DATA SECTION PUT$ #OUTFDB,R2,-2(R2) ;GET DATA FROM THE FILE BCC 10$ ;BR IF NO ERROR MOV #PUTERB,R0 ;WRITE ERROR CALL DSPMS ;DISPLAY THE MESSAGE 10$: MOV (SP)+,R0 ;RECOVER THE BUFFER ADDRESS CALL RETBF ;RETURN THE LINE BUFFER MOV (SP)+,R2 ;RESTORE R2 RETURN .SBTTL SUBRTN - SCROLL SCREEN UP, DOWN ;+ ; -SCRUP- SCROLL THE SCREEN UP ; ; INPUTS: ; NONE ; ; OUTPUTS: ; SCREEN IS SCROLLED UP, TOP LINE IS LOST ; CURSOR IS AT BOTTOM LEFT OS SCREEN ; R2 AND R3 ARE NOT CHANGED ;- LFP: .WORD LF ;LINEFEED SCRUP: CALL CLRBT MOV #1,QIOW+Q.IOPL+2 ;SEND A LINE FEED MOV #LFP,QIOW+Q.IOPL DIR$ #QIOW RETURN ;+ ; -SCRDN- SCROLL SCREEN DOWN ; ; INPUTS: ; NONE ; ; OUTPUTS: ; SCREEN HAS BEEN SCROLLED DOWN, TOP LINE IS BLANKED ; BOTTOM LINE HAS BEEN CLEARED ; CURSOR IS AT TOP LEFT OF SCREEN ; R2 AND R3 ARE NOR CHANGED ;- SCRDN: MOV R0,-(SP) ;SAVE R0 MOV R2,-(SP) ;SAVE R2 MOV R3,-(SP) ;SAVE R3 MOV #SC.LIN,R2 ;MOVE TO NEW BOTTOM LINE TO BE CLR R3 ;ON FAR LEFT CALL DSPPS ;MOVE TO POSITION CALL CLRLN ;CLEAR THE LINE MOV #'H,R0 ;SET TO HOME CALL DSPES ;MOVE TO POSITION MOV #'I,R0 ;SET TO SCROLL UP CALL DSPES ;SCROLL UP MOV (SP)+,R3 ;RESTORE R3 MOV (SP)+,R2 ;RESTORE R2 MOV (SP)+,R0 ;RESTORE R0 RETURN .SBTTL SUBRTN - CLEAR SCREEN, LINE, CLEAR BOTTOM LINE ;+ ; -CLRSC- CLEAR THE SCREEN ; -CLRLN- CLEAR THE END OF THE LINE ; ; INPUTS: ; NONE ; ; OUTPUTS: ; OPERATION IS PERFORMED ; ON CLEAR SCREEN, CURSOR IS LEFT AT TOP LEFT OF SCREEN ;- .ENABL LSB CLRSC: MOV R0,-(SP) ;SAVE R0 MOV #'H,R0 ;SET TO HOME CALL DSPES ;MOVE CURSOR MOV #'J,R0 ;SET TO CLEAR SCREEN BR 10$ CLRLN: MOV R0,-(SP) ;SAVE R0 MOV #'K,R0 ;SET TO CLEAR LINE 10$: CALL DSPES ;DO IT MOV (SP)+,R0 RETURN .DSABL LSB ;+ ; -CLRBT- CLEAR BOTTOM LINE OF SCREEN ; ; INPUTS: ; NONE ; ; OUTPUTS: ; CURSOR IS AT BOTTOM LEFT OF THE SCREEN ; R2 AND R3 ARE NOT CHANGED ;- CLRBT: MOV R0,-(SP) ;SAVE R0 MOV R2,-(SP) ;SAVE R2 MOV R3,-(SP) ;SAVE R3 MOV #27,R2 ;BOTTOM LINE CLR R3 ;FAR LEFT CALL DSPPS ;SET POSITION CALL CLRLN ;CLEAR THE LINE MOV (SP)+,R3 ;RESTORE R3 MOV (SP)+,R2 ;RESTORE R2 MOV (SP)+,R0 ;RESTORE R0 RETURN .SBTTL SUBRTN - DISPLAY CURRENT BUFFER ;+ ; -DSPBF- DISPLAY CONTENTS OF CURRENT BUFFER ON SCREEN ; ; THIS ROUTINE WILL DISPLAY AS MUCH OF THE BUFFER AREA AS POSSIBLE. ; THE DISPLAY WILL CENTER THE CURRENT LINE AT THE "SC.CUR" POSITION. ; ; INPUTS: ; R0 = 1 (DISPLAY ENTIRE BUFFER) ; = 2 (DISPLAY FROM CURRENT LINE TO THE END) ; = 3 (DISPLAY CURRENT CHARACTER TO END OF LINE) ; ; OUTPUTS: ; CURSOR IS PLACED PROPERLY ON SCREEN ;- DSPBF: TST R0 ;DO ANYTHING? BGT 3$ ;BR IF YES JMP 35$ ;JUST RETURN 3$: MOV R1,-(SP) ;SAVE R1 MOV R2,-(SP) ;SAVE R2 MOV R5,-(SP) ;SAVE R5 MOV R3,-(SP) ;SAVE R3 (IN ORDER) MOV R0,-(SP) ;SAVE R0 (IN ORDER) SUB #2,(SP) ;WHAT TO DISPLAY? BGT 28$ ;BR IF JUST END OF LINE BEQ 5$ ;BR IF ONLY BOTTOM OF SCREEN MOV #'H,R0 ;SET TO HOME CALL DSPES ;HOME THE CURSOR BR 8$ ;SKIP NEXT 5$: MOV #30,R2 ;STAY ON SAME LINE CLR R3 ;MOVE TO LEFT CALL DSPPS ;SET THE CURSOR 8$: MOV #SC.CUR,R2 ;SET TO NORMAL CURSOR LINE MOV BFCUR,R5 ;POINT AT CURRENT LINE TST (SP) ;DISPLAY ALL OR JUST BOTTOM? BEQ 20$ ;BR IF JUST BOTTOM TST R5 ;DO WE HAVE A CURRENT LINE BUFFER? BNE 10$ ;BR IF YES, USE IT MOV BFBOT,R5 ;POINT AT THE BOTTOM LINE THEN BEQ 15$ ;BR IF NONE AT ALL DEC R2 ;LINE SHOULD DISPLAY ONE LINE UP 10$: MOV 2(R5),R0 ;COPY BACK POINTER BEQ 15$ ;BR IF NONE MOV R0,R5 ;POINT AT PREVIOUS LINE BUFFER DEC R2 ;PREVIOUS LINE ON SCREEN BNE 10$ ;BR IF CAN FIT MORE BR 20$ ;GO DISPLAY THE LINES 15$: DEC R2 ;SET TO PREVIOUS LINE CLR R3 ;TEMPORARY LINE NUMBER, TOP OF SCREEN 17$: CALL CLRLN ;CLEAR THE LINE CMP R2,R3 ;AT PROPER LINE YET? BEQ 18$ ;BR IF YES MOV #'B,R0 ;SET TO MOVE DOWN A LINE CALL DSPES ;MOVE TO NEXT LINE INC R3 ;POINTING AT NEXT LINE BR 17$ ;CLEAR THAT ONE TOO 18$: CLR R3 ;POINT AT LEFT OF SCREEN CALL DSPBL ;DISPLAY THE BLOCK CHARACTER INC R2 ;POINT TO NEXT LINE 20$: MOV R5,R0 ;POINT AT LINE BUFFER BEQ 25$ ;BR IF NONE ADD #4,R0 ;POINT AT CHARACTER COUNT MOV (R0)+,R1 ;SET COUNT, POINT AT CHARACTERS CLR R3 ;START AT LEFT POSITION CALL DSPLN ;DISPLAY THE LINE INC R2 ;SET TO NEXT LINE CMP R2,#SC.LIN ;SCREEN NOW FULL? BGT 30$ ;BR IF YES MOV (R5),R5 ;POINT AT NEXT LINE BUFFER BNE 20$ ;GO DISPLAY IT 25$: CLR R3 ;NO NEXT LINE CALL DSPPS ;GO TO NEXT LINE ANYWAY CALL CLRLN ;CLEAR THE LINE CALL DSPBL ;DISPLAY A BLOCK CHARACTER MOV #'D,R0 ;SET TO BACK UP CALL DSPES ;GO BACK TO START OF LINE 26$: INC R2 ;CHECK NEXT LINE CMP R2,#SC.LIN ;PAST END OF SCREEN? BGT 30$ ;BR IF YES, FINISHED MOV #'B,R0 ;GO TO NEXT LINE CALL DSPES ;MOVE CURSOR CALL CLRLN ;CLEAR THE LINE BR 26$ 28$: MOV BFCUR,R0 ;POINT AT CURRENT BUFFER BEQ 30$ ;BR IF NOTHING TO DISPLAY CMP (R0)+,(R0)+ ;POINT AT CHARACTER COUNT MOV (R0)+,R1 ;GET COUNT, POINT AT CHARACTERS ADD BFPOS,R0 ;POINT AT CHARS TO DISPLAY SUB BFPOS,R1 ;NUMBER TO DISPLAY MOV #30,R2 ;STAY ON SAME LINE CALL DSPLN ;DISPLAY THE LINE 30$: MOV (SP)+,R0 ;RECOVER R0 MOV (SP)+,R3 ;RECOVER R3 MOV #SC.CUR,R2 ;POINT AT NORMAL CURSOR LINE CALL DSPPS ;SET THE POSITION MOV (SP)+,R5 ;RECOVER R5 MOV (SP)+,R2 ;RECOVER R2 MOV (SP)+,R1 ;RECOVER R1 35$: RETURN .SBTTL SUBRTN - DISPLAY MESSAGE ;+ ; -DSPMS- DISPLAY MESSAGE AT BOTTOM OF SCREEN ; ; INPUTS: ; R0 = ADDRESS OF MESSAGE ; ; OUTPUTS: ; MESSAGE IS DISPLAYED AT BOTTOM OF SCREEN IN REV. BOLD VIDEO ;RBD04 ; CURSOR REMAINS AT END OF MESSAGE ; R0 IS ALTERED ; R2 AND R3 ARE NOT CHANGED ;- S1: .ASCII "<""[7;1m" ;ANSI mode, Reverse bold video ;RBD04+ S1L = .-S1 S2: .ASCII "[m""[?2l" ;Normal video, VT-52 mode S2L = .-S2 ;RBD04- DSPMS: CALL CLRBT ;CLEAR THE BOTTOM LINE MOV #S1L,QIOW+Q.IOPL+2 ;SET ANSI MODE, REVERSE VIDEO ;RBD04 MOV #S1,QIOW+Q.IOPL ;RBD04 DIR$ #QIOW ;RBD04 MOV (R0)+,QIOW+Q.IOPL+2 ;SET THE COUNT MOV R0,QIOW+Q.IOPL ;SET THE ADDRESS DIR$ #QIOW ;DISPLAY LINE MOV #S2L,QIOW+Q.IOPL+2 ;NORMAL VIDEO, VT-52 MODE ;RBD04 MOV #S2,QIOW+Q.IOPL ;RBD04 DIR$ #QIOW ;RBD04 BIS #FL.MCD,FLAGS ;A MESSAGE IS UP RETURN .SBTTL SUBRTN - DISPLAY LINE ;+ ; -DSPLN- DISPLAY LINE PORTION ; ; THIS ROUTINE WILL DISPLAY A SPECIFIC PORTION OF A LINE AT A ; SPECIFIED SCREEN POSITION, KILLING WHAT WAS THERE BEFORE. ; ; INPUTS: ; R0 = POINTER TO FIRST CHARACTER OF DISPLAY ; R1 = COUNT OF CHARACTERS TO DISPLAY (BETWEEN 1 AND 132. INCLUSIVE) ; R2 = SCREEN LINE # (0 TO 27, 30 FOR SAME LINE WITH NO FLICKER) ; R3 = COLUMN # (0 TO 117) ; ; OUTPUTS: ; LINE IS DISPLAYED ; R3 = NEW COLUMN # ;- DSPLN: MOV R0,-(SP) ;SAVE R0 MOV R1,-(SP) ;SAVE R1 MOV R4,-(SP) ;SAVE R4 CMP R3,NMCOL ;PAST END OF DISPLAY? BGE 30$ ;BR IF YES, NO CHANGE MOV R1,R4 ;SAVE THE CHARACTER COUNT MOV #DSPLNB+2,R1 ;POINT AT THE BUFFER MOV R2,-(SP) ;SAVE R2 MOV R3,-(SP) ;SAVE R3 ADD #40,R2 ;OFFSET THE LINE BY 40 CMP R3,NMCOL ;POSITION PAST END OF SCREEN? BLT 5$ ;BR IF NO MOV NMCOL,R3 ;PLACE AT END OF SCREEN CMP R3,#80. ;IS IT REALLY PAST EDGE? BEQ 3$ ;BR IF YES CMP R3,#132. ;MIGHT BE A VT100 BNE 5$ ;ASSUME NO 3$: DEC R3 ;BACK UP TO LAST COLUMN 5$: ADD #40,R3 ;OFFSET THE COLUMN BY 40 MOVB R2,(R1)+ ;SET THE LINE NUMBER MOVB R3,(R1)+ ;SET THE COLUMN NUMBER MOV (SP)+,R3 ;RECOVER R3 MOV (SP)+,R2 ;RECOVER R2 CMPB (R1)+,(R1)+ ;SKIP OVER THE "KILL" BYTES TST R4 ;ANYTHING IN THE LINE? BEQ 15$ ;BR IF NO 10$: CALL TRNCR ;TRANSLATE FOR OUTPUT CMP R3,NMCOL ;NOW PAST END OF DISPLAY? BGE 15$ ;BR IF YES CMP R1,#DSPLNB+136. ;CAN ONLY DISPLAY 132. BGE 15$ ;BR IF MORE DEC R4 ;COUNT CHARACTERS BGT 10$ ;BR IF MORE 15$: SUB #DSPLNB,R1 ;GET CHARACTER COUNT CMP R1,#138. ;CAN ONLY DISPLAY 132 CHARS BLE 20$ ;BR IF OK MOV #138.,R1 ;RESET THE COUNT 20$: MOV #DSPLNB,QIOW+Q.IOPL ;SET THE BUFFER ADDRESS MOV R1,QIOW+Q.IOPL+2 ;SET THE COUNT DIR$ #QIOW ;DISPLAY THE BUFFER 30$: MOV (SP)+,R4 ;RECOVER R4 MOV (SP)+,R1 ;RECOVER R1 MOV (SP)+,R0 ;RECOVER R0 RETURN .SBTTL SUBRTN - DISPLAY CHARACTER, DISPLAY BLOCK CHARACTER ;+ ; -DSPCR- DISPLAY A SINGLE CHARACTER ; ; THIS ROUTINE DISPLAYS ONE CHARACTER AT THE CURRENT SCREEN POSITION ; ; INPUTS: ; R0 = CHARACTER ; R3 = CURRENT COLUMN # (0 TO 117) ; ; OUTPUTS: ; THE CHARACTER IS DISPLAYED ; R3 = NEW COLUMN # ;- DSPCR: CMP R3,NMCOL ;IS CURSOR ON FAR RIGHT ALREADY? BGE 10$ ;BR IF YES, NO MORE CHARS DISPLAYED MOV R0,-(SP) ;SAVE R0 MOV R1,-(SP) ;SAVE R1 MOVB R0,DSPCRB ;PLACE CHARACTER IN BUFFER MOV #DSPCRB,R0 ;POINT AT BUFFER MOV R0,R1 ;POINT AT SAME BUFFER CALL TRNCR ;TRANSLATE FOR OUTPUT SUB #DSPCRB,R1 ;GET LENGTH TO OUTPUT MOV #DSPCRB,QIOW+Q.IOPL ;SET THE BUFFER ADDRESS MOV R1,QIOW+Q.IOPL+2 ;SET THE COUNT DIR$ #QIOW ;DISPLAY IT MOV (SP)+,R1 ;RESTORE R1 MOV (SP)+,R0 ;RESTORE R0 10$: RETURN ;+ ; -DSPBL- DISPLAY A BLOCK CHARACTER ; ; OUTPUTS: ; CURSOR IS PLACED AFTER THE BLOCK CHARACTER ON THE SCREEN ;- DSPBL: MOV R0,-(SP) ;SAVE R0 MOV #'F,R0 ;SET TO ENTER GRAPHICS CALL DSPES ;ENTER GRAPHICS MODE MOV #141,R0 ;DISPLAY BLOCK CHARACTER CALL DSPCR ;AS END OF BUFFER MARK MOV #'G,R0 ;AND SET TO EXIT GRAPHICS CALL DSPES ;EXIT GRAPHICS MODE MOV (SP)+,R0 RETURN .SBTTL SUBRTN - DISPLAY POSITION ;+ ; -DSPPS- DISPLAY THE CURSOR POSITION ; ; THIS ROUTINE DISPLAYS THE INDICATED CURSOR POSITION ; ; INPUTS: ; R2 = LINE # (0=TOP, 27=BOTTOM, 30=NO VERTICAL MOVEMENT) ; R3 = COLUMN # (0=LEFT, 117=RIGHT) ; ; OUTPUTS: ; THE CURSOR POSITION IS CHANGED ;- DSPPS: MOV R2,-(SP) ;SAVE R2 MOV R3,-(SP) ;SAVE R3 ADD #40,R2 ;OFFSET LINE BY 40 CMP R3,NMCOL ;POSITION PAST END OF SCREEN? BLT 10$ ;BR IF NO MOV NMCOL,R3 ;PLACE AT END OF SCREEN CMP #80.,R3 ;IS NMCOL AT END OF SCREEN? BEQ 5$ ;BR IF YES CMP #132.,R3 ;FOR VT100, 132 COLUMNS IS LEGAL BNE 10$ ;BR IF NO 5$: DEC R3 ;ASSUME ILLEGAL COLUMN, BACK UP ONE 10$: ADD #40,R3 ;OFFSET COLUMN BY 40 MOVB R2,DSPPSB+2 ;PLACE LINE IN BUFFER MOVB R3,DSPPSB+3 ;PLACE COLUMN IN BUFFER MOV #DSPPSB,QIOW+Q.IOPL ;SET THE BUFFER ADDRESS MOV #4,QIOW+Q.IOPL+2 ;SET THE COUNT DIR$ #QIOW ;DISPLAY IT MOV (SP)+,R3 ;RECOVER R3 MOV (SP)+,R2 ;RECOVER R2 RETURN .SBTTL SUBRTN - DISPLAY ESCAPE SEQUENCE ;+ ; -DSPES- DISPLAY A SINGLE CHARACTER ESCAPE SEQUENCE ; ; THIS ROUTINE DISPLAYS AN ESCAPE SEQUENCE OF "ESCAPE" PLUS ONE CHARACTER ; ; INPUTS: ; R0 = CHARACTER ; ; OUTPUTS: ; THE ESCAPE SEQUENCE IS DISPLAYED ;- DSPES: MOVB R0,DSPESB+1 ;PLACE CHARACTER IN BUFFER MOV #DSPESB,QIOW+Q.IOPL ;SET THE BUFFER ADDRESS MOV #2,QIOW+Q.IOPL+2 ;SET THE COUNT DIR$ #QIOW ;DISPLAY IT RETURN .SBTTL SUBRTN - ASK IF USER IS SURE ;+ ; -ASKSR- ASK USER IF OPERATION MAY CONTINUE ; ; INPUTS: ; R0 = ADDRESS OF "ASK" MESSAGE ; ; OUTPUTS: ; R0 = FIRST CHARACTER OF ANSWER ;- ASKSR: MOV R1,-(SP) ;SAVE R1 MOV R4,-(SP) ;SAVE R4 CALL DSPMS ;ASK IF USER IS SURE MOV #BFTMP,R0 ;USE TEMPORARY BUFFER MOV #NM.CHR,R1 ;FOR INPUT CLRB (R0) ;IN CASE HE TYPES NOTHING CALL INLIN ;GET USER INPUT CALL CLRBT ;CLEAR THE BOTTOM LINE MOV (SP)+,R4 ;RESTORE R4 MOV (SP)+,R1 ;RESTORE R1 MOVB (R0),R0 ;GET ANSWER BIC #40,R0 ;MAKE SURE ITS UPPER CASE RETURN .SBTTL SUBRTN - INPUT LINE FROM TTY ;+ ; -INLIN- INPUT A LINE FROM THE TERMINAL ; DETACH/ATTACH SERVES TO FLUSH TYPEAHEAD IN PREPARATION ;RBD01 ; FOR USER INPUT LINE OF TEXT. ;RBD01 ; ; INPUTS: ; R0 = ADDRESS OF INPUT BUFFER ; R1 = MAXIMUM INPUT COUNT ; ; OUTPUTS: ; CARRY = CLEAR ; LINE HAS BEEN INPUT ; R1 CONTAINS CHARACTER COUNT ; R4 CONTAINS THE TERMINATOR CHARACTER ; CARRY = SET ; USER HAS INPUT A CONTROL-Z ;- INLIN: MOV R0,-(SP) ;SAVE R0 MOV R0,INLINQ+Q.IOPL ;SET THE ADDRESS MOV R1,INLINQ+Q.IOPL+2 ;SET THE COUNT DIR$ #INLINQ ;INPUT BCS 10$ ;BR IF NO GOOD TSTB $DSW ;DIRECTIVE WORKED? BLE 5$ ;BR IF NO TSTB INLINS ;INPUT WORKED? BGT 10$ ;BR IF YES 5$: SEC ;ASSUME END-OF-FILE 10$: MOV INLINS+2,R1 ;GET CHARACTER COUNT MOVB INLINS+1,R4 ;GET TERMINATOR CHARACTER MOV (SP)+,R0 ;RESTORE R0 RETURN .SBTTL SUBRTN - INPUT CHARACTER FROM TTY ;+ ; -INCHR- RETRIEVE CHARACTERS INPUT FROM TERMINAL ; COMPLETELY NEW FOR RSX V3.2/FDX ;RBD01 ; ; INPUTS: ; NONE ; ; OUTPUTS: ; R0 = CHARACTER INPUT FROM TTY ;- INCHR: DIR$ #INCHRQ ;READ A CHARACTER MOVB INLST,R0 ;COPY TO R0 BIC #^C<177>,R0 ;CLEAR ALL NON-ESSENTIAL BITS MOV R0,INLST ;SET "LAST CHAR INPUT" RETURN ;DONE .SBTTL SUBRTN - PARSE FILE NAME ;+ ; -PRSFL- PARSE FILE NAME FOR FILE DESCRIPTOR BLOCK ; ; INPUTS: ; R0 = ADDRESS OF FILE NAME BUFFER ; R1 = NUMBER OF CHARACTERS IN NAME ; R4 = ADDRESS OF FILE NAME DESCRIPTOR BLOCK ; ; OUTPUTS: ; FILE NAME IS PARSED ;- PRSFL: MOV R0,-(SP) ;SAVE R0 MOV R1,-(SP) ;SAVE R1 MOV R2,-(SP) ;SAVE R2 MOV R3,-(SP) ;SAVE R3 MOV R4,-(SP) ;SAVE R4 MOV #4,(R4)+ ;ASSUME DEFAULT DEVICE MOV #DFDEV,(R4)+ ;WHICH IS SY0: MOV R0,R2 ;POINT AT FILE NAME MOV R1,R3 ;COPY THE COUNT 10$: CMPB (R2)+,#': ;LOOK FOR A DEVICE TERMINATOR BEQ 15$ ;BR IF FOUND ONE DEC R3 ;COUNT CHARACTERS BGT 10$ ;BR IF MORE TO TRY BR 20$ ;BR IF NO DEVICE 15$: DEC R3 ;GET COUNT OF WHATS LEFT SUB R3,R1 ;LENGTH OF DEVICE NAME MOV R0,-(R4) ;SET DEVICE NAME ADDRESS MOV R1,-(R4) ;SET DEVICE NAME LENGTH CMP (R4)+,(R4)+ ;POINT AT NEXT FIELD MOV R2,R0 ;POINT AT REST OF FILE NAME MOV R3,R1 ;GET LEFTOVER COUNT 20$: CLR (R4)+ ;ASSUME NO UIC CLR (R4)+ CMPB (R0),#'[ ;IS THERE A UIC? BNE 30$ ;BR IF NO MOV R1,R3 ;GET COUNT MOV R0,-(R4) ;SET ADDRESS 25$: DEC R1 ;COUNT DOWN FOR WHATS LEFT CMPB (R0)+,#'] ;END OF UIC? BNE 25$ ;BR IF NO SUB R1,R3 ;GET LENGTH OF UIC MOV R3,-(R4) ;SET THE LENGTH CMP (R4)+,(R4)+ ;POINT AT THE NEXT FIELD 30$: MOV R1,(R4)+ ;MOVE IN COUNT FOR NAME BGT 35$ ;BR IF SOMETHING THERE CLR R0 ;SET NO ADDRESS 35$: MOV R0,(R4) ;SET ADDRESS OF NAME MOV (SP)+,R4 ;RESTORE R4 MOV (SP)+,R3 ;RESTORE R3 MOV (SP)+,R2 ;RESTORE R2 MOV (SP)+,R1 ;RESTORE R1 MOV (SP)+,R0 ;RESTORE R0 RETURN .SBTTL SUBRTN - TRANSLATE HORIZONTAL SCREEN POSITION ;+ ; -TRNPS- TRANSLATE HORIZONTAL SCREEN POSITION ; ; INPUTS: ; R0 = ADDRESS OF START OF CHARACTERS ; R2 = COUNT OF CHARACTERS ; R3 = STARTING HORIZONTAL SCREEN POSITION ; ; OUTPUTS: ; R3 = POSITION ON SCREEN IF CHARACTERS ARE TRANSLATED AND OUTPUT ;- TRNPS: MOV R0,-(SP) ;SAVE R0 MOV R1,-(SP) ;SAVE R1 MOV R2,-(SP) ;SAVE R2 CLR R1 ;NO TRANSLATION BUFFER 10$: CALL TRNCR ;UPDATE POSITION FOR ONE CHARACTER DEC R2 ;COUNT CHARACTERS BGT 10$ ;BR IF MORE CMP R3,NMCOL ;IS CURSOR OFF END OF SCREEN? BLE 20$ ;BR IF NO MOV NMCOL,R3 ;PLACE POSITION AT ONE PAST EDGE 20$: MOV (SP)+,R2 ;RECOVER R2 MOV (SP)+,R1 ;RECOVER R1 MOV (SP)+,R0 ;RECOVER R0 RETURN .SBTTL SUBRTN - TRANSLATE CHARACTER FOR OUTPUT ;+ ; -TRNCR- TRANSLATE CONTROL CHARACTERS FOR OUTPUT ; ; INPUTS: ; R0 = POINTER TO CHARACTER TO OUTPUT ; R1 = POINTER TO OUTPUT BUFFER ; R3 = CURRENT SCREEN COLUMN ; IF R1 IS ZERO, THERE IS NO OUTPUT BUFFER ; ; OUTPUTS: ; R0 = POINTER TO NEXT CHARACTER TO OUTPUT ; R1 = POINTER TO NEXT POSITION IN OUTPUT BUFFER ; R3 = NEW SCREEN COLUMN ;- TRNPG: .ASCII "" TRNPL= .-TRNPG .EVEN TRNCR: INC R3 ;OUTPUT AT LEAST ONE CHARACTER CMPB #177,(R0) ;DELETE CHARACTER? BEQ 10$ ;BR IF YES CMPB #33,(R0) ;ESCAPE? BEQ 15$ ;BR IF YES CMPB #14,(R0) ;FORM-FEED? BEQ 18$ ;BR IF YES CMPB #11,(R0) ;TAB? BEQ 20$ ;BR IF YES CMPB #40,(R0) ;ORDINARY CONTROL CHARACTER? BLE 25$ ;BR IF NO 10$: INC R3 ;TWO SPACES PER CONTROL CHARACTER TST R1 ;IS THERE AN OUTPUT BUFFER? BEQ 35$ ;BR IF NO MOVB (R0),1(R1) ;INSERT CHARACTER MOVB #'^,(R1)+ ;PRECEED BY UP-ARROW BICB #100,(R1) ;IN CASE ITS A DELETE CMPB #40,(R1) ;ALREADY UPPER-CASE? BLE 30$ ;BR IF YES BISB #100,(R1)+ ;CONVERT TO UPPER-CASE BR 35$ 15$: MOVB #'$,(R1)+ ;INSERT A DOLLAR (ESCAPE) BR 35$ 18$: ADD #TRNPL-1,R3 ;SET COUNT TST R1 ;IS THERE AN OUTPUT BUFFER? BEQ 35$ ;BR IF NO MOV R2,-(SP) ;SAVE R2 MOV R3,-(SP) ;SAVE R3 MOV #TRNPG,R2 ;PAGE MARK BUFFER MOV #TRNPL,R3 ;AND LENGTH 19$: MOVB (R2)+,(R1)+ ;MOVE IN LONG TRANSLATION DEC R3 ;ANY LEFT? BGT 19$ ;BR IF YES MOV (SP)+,R3 ;RESTORE R3 MOV (SP)+,R2 ;RESTORE R2 BR 35$ 20$: ADD #7,R3 ;UPDATE TO NEXT TAB STOP BIC #7,R3 ;CLEAR LOW ORDER BITS 25$: TST R1 ;IS THERE AN OUTPUT BUFFER? BEQ 35$ ;BR IF NO MOVB (R0),(R1) ;INSERT CHARACTER 30$: INC R1 ;UPDATE OUTPUT BUFFER POINTER 35$: INC R0 ;UPDATE CHARACTER POINTER RETURN .SBTTL SUBRTN - CONVERT INPUT TO UPPER CASE ;+ ; -CNVLUC- CONVERT LOWER TO UPPER CASE ON INPUT ; ; INPUTS: ; R0 = ADDRESS OF START OF CHARACTERS ; R1 = COUNT OF CHARACTERS ; ; OUTPUTS: ; ALL LOWER CASE ALPHA HAS BEEN CONVERTED TO UPPER CASE ;- CNVLUC: MOV R0,-(SP) ;SAVE R0 MOV R1,-(SP) ;SAVE R1 10$: CMPB (R0)+,#'A+40 ;IS THIS LOWER CASE? BLT 20$ ;BR IF NO BICB #40,-1(R0) ;MAKE IT UPPER CASE 20$: DEC R1 ;COUNT DOWN BGT 10$ ;BR IF MORE MOV (SP)+,R1 ;RESTORE R1 MOV (SP)+,R0 ;RESTORE R0 RETURN .SBTTL SUBRTN - LINE BUFFER POOL CONTROL ;+ ; -GETBF- GET A LINE BUFFER FROM THE FREE POOL ; ; INPUTS: ; NONE ; ; OUTPUTS: ; CARRY = CLEAR ; R0 = ADDRESS OF LINE BUFFER ; CARRY = SET ; NO LINE BUFFER AVAILABLE ;- GETBF: SEC ;ASSUME FAILURE MOV BFUBP,R0 ;GET LINE BUFFER ADDRESS BEQ 10$ ;BR IF NONE MOV (R0),BFUBP ;RESET TO NEXT LINE BUFFER INC BFALL ;ANOTHER BUFFER ALLOCATED CLC ;SUCCESS 10$: RETURN ;+ ; -RETBF- RETURN A LINE BUFFER TO THE FREE POOL ; ; INPUTS: ; R0 = LINE BUFFER ADDRESS ; ; OUTPUTS: ; NONE ;- RETBF: MOV BFUBP,(R0) ;LINK NEW BUFFER INTO POOL MOV R0,BFUBP ;POINT POOL AT NEW BUFFER DEC BFALL ;ONE LESS BUFFER ALLOCATED RETURN .END ICE