;Edit number 63 by SST.D-BIGELOW on 7-Aug-85 ; Fix bug in reverse searching which prevented error message from ; being printed. ; ;Edit number 62 by SST.D-BIGELOW on 6-Aug-85 ; Revise special character set that marks paragraph break: add ], ; remove @. ; ;Edit number 60 by SST.D-BIGELOW on 18-Jun-85 ; Correct bug in edit 56; could break on null(space) at bol. ; ;Edit number 57 by SST.D-BIGELOW on 17-Jun-85 ; Add processing for Rainbow function keys, which generate a sequence ; like $[(number)~. ; ;Edit number 56 by SST.D-BIGELOW on 11-Jun-85 ; Expand the set of special characters that mean new paragraph when ; encountered at BOL during evening. ; ;Edit number 55 by SST.D-BIGELOW on 11-Jun-85 ; Make label PTRTAB external for WPSIM, and make the UNFILL routine ; always terminate with nulls rather than deletes. ; ;Edit number 54 by SST.D-BIGELOW on 10-Jun-85 ; Make a delete at beginning of line move the cursor to the end of the ; previous line. ; ;Edit number 53 by SST.D-BIGELOW on 5-Sep-84 ; Prevent control character conversion during regular screen updates, ; since the escape codes affect the screen. ; ;Edit number 52 by SST.D-BIGELOW on 22-Jun-84 ; Fix problem with freezing WPSIM due to column overflow: COL>80. Make ; the ^KM routine refuse column 79, and make CURPOS work modulo 80. ; ;Edit number 51 by SST.D-BIGELOW on 29-Mar-84 ; Add new command ^VA, to even all of a double spaced input file. ; ;Edit number 50 by SST.D-BIGELOW on 28-Mar-84 ; Fix problem with page mark display routine. Make the SPCON and SPCOFF ; routines pay attention to the order in which they are called. ; ;Edit number 47 by SST.D-BIGELOW on 28-Mar-84 ; Add a /VT102 switch, which is required for special insert and delete ; code for VT100 terminals. ; ;Edit number 46 by SST.D-BIGELOW on 27-Feb-84 ; Correct bug in ^DB routine introduced for ANSI terminals. ; ;Edit number 45 by SST.D-BIGELOW on 22-Feb-84 ; Make ^^ in function string yield an up-arrow in command. ; ;Edit number 44 by SST.D-BIGELOW on 22-Feb-84 ; Make first page 4 lines longer when autopaginating. Make up for the ; lack of a header on the first page. ; ;Edit number 43 by SST.D-BIGELOW on 9-Feb-84 ; Correct bugs when inserting or deleting too many lines or characters ; is attempted. Work manually if more than 23 lines or 78 characters. ; ;VDT.MAC.13, 29-Jan-84 20:12:49, Edit by SST.P-GALVIN ; 42 Implement /Search mode. If set, we call PATMAT instead of displaying ; the first screen, and don't display the full screen until ^L is typed ; or a routine which calls .FFD is executed. All commands are usable ; after the first search. Areas effected: GETTXT, PATMAT, and TYPLIN ; ;VDT.MAC.14, 11-Jan-84 18:29:03, Edit by SST.P-GALVIN ; 41 Implement VT100 insertion and deletion of lines (let the terminal ; do the work. ; ;VDT.MAC.3, 11-Jan-84 12:00:35, Edit by SST.P-GALVIN ; 40 Take advantage of the alternate keypad mode on VT100s to allow ; more function keys. ; ;VDT.MAC.2, 21-Dec-83 16:31:22, Edit by SST.D-BIGELOW ; 37 Control-K;H modifications: make cancel the old header, but any ; number of blanks followed by set to paging style two with no ; left margin header. ; ;VDT.MAC.2, 5-Dec-83 10:33:42, Edit by SST.D-BIGELOW ; 36 Make the header input routine more defensive. Handle a header that ; doesn't end with a null by looking for control characters as we read, ; and ending as soon as we find one. ; ;VDT.MAC.5, 31-Oct-83 17:43:35, Edit by SST.D-BIGELOW ; 35 Fix problem where double-spaced downward scrolling broke when the ; cursor was on the last line of the screen. ; ;VDT.MAC.4, 31-Oct-83 16:30:09, Edit by SST.D-BIGELOW ; 34 Correct problem with scrolling upwards in double spaced mode. Scroll ; value was being overwritten by two. ; ;VDT.MAC.3, 10-Oct-83 12:29:18, Edit by SST.D-BIGELOW ; 33 Change VT100 (ansi) terminal upward scrolling routine to take account ; of status of double flag. ; ;VDT.MAC.40, 28-Sep-83 13:37:47, Edit by SST.D-BIGELOW ; 32 Allow a carriage return input to the get header routine to clear out ; a page header and restore -n- style. ; ;VDT.MAC.33, 27-Sep-83 10:53:43, Edit by SST.D-BIGELOW ; 31 Correct problem with autopagination double-counting the first line of ; a new page, causing the last lines of a file to disappear. ; ;VDT.MAC.8, 15-Sep-83 15:19:26, Edit by SST.D-BIGELOW ; 30 Rewrite the justify routine to handle any combinations of margins and ; spacing conditions. ; ;VDT.MAC.6, 17-Aug-83 12:59:42, Edit by SST.P-GALVIN ; 27 Make ^KP toggle pagination; Make ^KB Set a page break after inserting ; a new line; Make ^KD Set double spacing and get rid of ^KT; Make ; routines more reluctant to call setpag: .Hom, Posit, BakTab, TraTab, ; Patmat, Search, Getlin, .Tab, .FFD, Insert, Deleol ; ;VDT.MAC.11, 11-Aug-83 17:02:17, Edit by SST.D-BIGELOW ; 25 Completely rewrite fill and empty to handle new style of pagination, ; remove AJ support, and increase speed and efficiency. ; ;VDT.MAC.2, 30-Jun-83 11:43:25, Edit by SST.D-BIGELOW ; 24 Correct FILL and EMPTY routines to work properly with new techniques ; of terminating file with delete. ; ;VDT.MAC.28, 21-Jun-83 13:52:56, Edit by SST.D-BIGELOW ; 23 Fix longstanding bug in the JOIN routine: if you attempt to do a ; join when the cursor is past the margin, routine returns without ; popping the stack first. ; ;VDT.MAC.27, 20-Jun-83 17:18:31, Edit by SST.P-GALVIN ; 22 Attempted the impossible: Floating (wordstar-like) pagination on ; a mainframe computer. ; ;VDT.MAC.3, 16-Jun-83 13:36:32, Edit by SST.P-GALVIN ; 21 Made ^KA (adjust margin) only change the left margin if ; we're in program mode. ; ;VDT.MAC.2, 18-Mar-83 15:16:11, Edit by SST.P-GALVIN ; 20 Started implementing a new algorithm for single and double spacing. ; This one depends on the mode selected by ^KT, and flag DOUBLE is set ; if we are double-spacing. ; ;VDT.MAC.2, 7-Mar-83 15:12:13, Edit by SST.D-GALVIN ; 17 Patch the FILL routine to eliminate hanging if no modified ; SIN% JSYS is being used. ; ;VDT.MAC.3, 1-Mar-83 11:08:51, Edit by SST.P-GALVIN ; 16 Add an error message if control-c trap enabling fails (for ; the MIT exec and Batch). ; ;VDT.MAC.2, 17-Feb-83 14:14:34, Edit by SST.D-BIGELOW ; 15 Add the ^KA command to adjust the margins via the shrink amount. ; This allows toggling of note style margins in and out. ; ;VDT.MAC.38, 29-Jan-83 16:06:37, Edit by SST.P-GALVIN ; 14 Change the ^PP and ^PN commands so that the cursor remains on the ; same screen line as it was before the command was issued. This ; does not effect these commmands when they are preceeded by a ; numeric arguement. ; ;VDT.MAC.35, 28-Jan-83 17:48:34, Edit by SST.P-GALVIN ; 13 Implemented reverse search and replacment. Repeat search and replace ; also knows how to behave, and so goes in the proper direction. ; ;VDT.MAC.2, 31-Dec-82 08:17:48, Edit by SST.D-BIGELOW ; 12 Add processing for a new wpsim switch /NUMBER:n which allows starting ; page numbering at any desired place. ; ;VDT.MAC.2, 9-Dec-82 16:38:21, Edit by SST.P-GALVIN ; 11 Create a section of the UNFILL routine which checks the ; CTRLCV word to see whether it should convert ; "$"'s to ""'s and "^"'s to control's. ; ;VDT.MAC.2, 1-Dec-82 16:08:07, Edit by SST.P-GALVIN ; 10 Change empty algorithm to avoid problems with filtab switch being ; set. Add new switch F.TABC. ; ;VDT.MAC.5, 22-Nov-82 13:37:04, Edit by SST.P-GALVIN ; 7 Implement a new command "^KZ", which toggles "zero output", i.e. ; output to nowhere, on and off. The startup value is on. ; ;VDT.MAC.2, 18-Oct-82 11:08:37, Edit by SST.D-BIGELOW ; 6 Change the insert mode so that it only inserts lines when it has ; reached new territory -- allow editing within inserts. ; ;VDT.MAC.3, 15-Oct-82 11:22:53, Edit by SST.D-BIGELOW ; 5 Modify the help file to reflect the changed commands. ; ;VDT.MAC.13, 14-Oct-82 14:43:46, Edit by SST.D-BIGELOW ; 4 Turn off /MODEL2 if not a Viewpoint. Remove ^S/^Q from list of ; commands, use ^KW for ^S and new search command for ^Q. Changed ; format of search failure messages. ; ;VDT.MAC.2, 7-Oct-82 09:08:09, Edit by SST.D-BIGELOW ; 3 Fix problem where double spacing fails when reading in a single ; spaced input file. ; ;VDT.MAC.6, 28-Sep-82 16:59:22, Edit by SST.D-BIGELOW ; 2 Correct problem reading in doubled files without the correct ; number of trailing blank lines -- add erjmp after sin. ; ;VDT.MAC.3, 28-Sep-82 15:19:23, Edit by SST.D-BIGELOW ; 1 Start VDT edit history -- WPSIM now loads an external version ; number which includes VDT edit in the edit number. ; ;VDT.MAC.2, 28-Sep-82 14:55:55, Edit by SST.D-BIGELOW ; Fix a nasty bug that blows up programs when you are converting ; output and a ~ line ends the file. ; ;VDT.MAC.2, 27-Sep-82 15:26:44, Edit by SST.D-BIGELOW ; Correct problem in repeat search routine -- cursor left in wrong ; place if search fails before N runs out. ; ;VDT.MAC.4, 22-Sep-82 18:32:27, Edit by SST.D-BIGELOW ; Correct more problems with replacement routine, and make the ^KN ; routine clear the screen before refreshing. ; ;VDT.MAC.2, 8-Sep-82 16:40:26, Edit by SST.D-BIGELOW ; Add ^PT routine to make the current line scroll to the top of the ; screen. ; ;VDT.MAC.2, 8-Sep-82 14:23:57, Edit by SST.D-BIGELOW ; Make change in insert file routine to prevent error in gtjfn from ; leaving reverse video on. ; ;VDT.MAC.2, 7-Sep-82 10:44:28, Edit by SST.D-BIGELOW ; Make a change in the output ciphering routine so that the last line of ; text would get properly ciphered. ; ;VDT.MAC.2, 3-Sep-82 12:42:59, Edit by SST.D-BIGELOW ; Add ^KV command to help message. Subtracted a line from the numeric ; repeat count explanation to make room for it. ; ;VDT.MAC.2, 1-Sep-82 13:24:04, Edit by SST.D-BIGELOW ; Make the EMPTY routine smarter about counting -- it was converting ; (hghlin-1) lines of text. ; ;VDT.MAC.10, 31-Aug-82 20:10:15, Edit by SST.D-BIGELOW ; Correct input file reading section -- don't use typerr for errors. ; Instead use type with rfpos% to see where we are. ; ;VDT.MAC.7, 31-Aug-82 12:35:51, Edit by SST.D-BIGELOW ; Now implement upward scrolling, using the same logic as the downward ; scrolling feature. Amount to scroll is variable. ; ;VDT.MAC.3, 30-Aug-82 17:10:29, Edit by SST.D-BIGELOW ; Implement downward scrolling on the VT100 terminals, by use of the ; reverse index command. ; ;VDT.MAC.4, 30-Aug-82 14:59:29, Edit by SST.D-BIGELOW ; Add commands to save and restore the cursor attributes when using ; special effects on a VT100 terminal. ; ;VDT.MAC.3, 26-Aug-82 14:49:44, Edit by SST.D-BIGELOW ; Make correction to $>R routine to prevent TOPLIN from ever becoming ; negative. ; ;VDT.MAC.3, 20-Aug-82 17:06:30, Edit by SST.D-BIGELOW ; Make POSELN routine position to end of line even if past the end. ; If blank line, just return. ; ;VDT.MAC.2, 20-Aug-82 13:04:48, Edit by SST.D-BIGELOW ; Make the empty routine eliminate trailing spaces as well as trailing ; tabs. ; ;VDT.MAC.3, 20-Aug-82 11:37:27, Edit by SST.P-GALVIN ; Allow interractive function redefinition (up to 70 characters in ; a function). ; ;VDT.MAC.16, 15-Aug-82 16:01:46, Edit by SST.P-GALVIN ; Implement the $>R (return) command. Return the cursor to the ; location of the $< command. This command enables you to leave ; an ancor in the file, and return to it at anytime (up till the ; next $< command is executed. ; ;VDT.MAC.9, 15-Aug-82 14:06:30, Edit by SST.P-GALVIN ; Implemented the ^KN command: Kill the current buffer and input ; a new file for editing. ; ;VDT.MAC.43, 13-Aug-82 14:22:24, Edit by SST.D-BIGELOW ; Finish implementation of replacement for long strings. ; ;VDT.MAC.33, 13-Aug-82 10:10:38, Edit by SST.D-BIGELOW ; Rewrite LINLEN routine and modify replacement algorithms. ; ;VDT.MAC.31, 13-Aug-82 08:22:22, Edit by SST.D-BIGELOW ; Modify algorithm for inserting spaces. Terminate with error message ; if we try to insert too many spaces. ; ;VDT.MAC.29, 12-Aug-82 18:51:43, Edit by SST.P-GALVIN ; Make the REPLACE command work with replacement strings longer ; than the search string. It still won't work if the old line ; would be longer than 80 characters with the replacement ; ;VDT.MAC.5, 10-Aug-82 09:43:51, Edit by SST.D-BIGELOW ; Change "undefined terminal type" message so that it doesn't undefine ; the terminal before exiting. Make repeat counts work for arrow keys ; on DEC terminals. ; ;VDT.MAC.2, 9-Aug-82 10:31:57, Edit by SST.D-BIGELOW ; Implement tabifying on output if requested by filtab switch. Convert ; multiple spaces to tabs. ; ;VDT.MAC.3, 6-Aug-82 14:15:27, Edit by SST.D-BIGELOW ; Change save buffer parameters -- counts were wrong and buffers were ; overflowing. Allow 144 lines, 3100 words, 17500 characters. (Octal) ; ;VDT.MAC.2, 6-Aug-82 11:59:01, Edit by SST.D-BIGELOW ; Add new method of displaying proper screen after a continued ctrl-C. ; Force a ^L into input buffer after continuing. Also remove some error ; messages from expert mode typout, and fix a bug in movpar processing. ; ;VDT.MAC.16, 1-Aug-82 12:50:45, Edit by SST.B-RAMSEY ; Fix the maximum line checking code in FILL so that input is terminated ; at Maxlin rather than at Maxlin-1 lines. ; ;VDT.MAC.2, 31-Jul-82 15:19:45, Edit by SST.P-GALVIN ; Implement a faster form of File <--> Buffer I/O. ; This one depends on the modified SIN% JSYS. ; ;VDT.MAC.7, 29-Jul-82 10:41:43, Edit by SST.P-GALVIN ; Implement the VT52 (GIGI) terminal type. ; ;VDT.MAC.2, 20-Jul-82 15:39:36, Edit by SST.D-BIGELOW ; Adjust the maximum line checking routines to be at the character input ; routine rather than just after a down command. ; ;VDT.MAC.3, 20-Jul-82 10:42:44, Edit by SST.B-RAMSEY ; Define as Internal MATCH and MAKTAB so that the pattern-matching ; routines may be called from external programs. ; ;VDT.MAC.2, 19-Jul-82 15:37:39, Edit by SST.D-BIGELOW ; Beginning of edit history. Add intercept to pick up failure ; of STI% jsys before the input buffer fills up. ; Subttl Table of contents for VDT ; -- Section -- -- Page -- ; ; 1. Edit history.................................................. 1 ; 2. Table of contents............................................. 2 ; 3. Title page.................................................... 3 ; 4. Program flag definitions...................................... 4 ; 5. Terminal definitions.......................................... 6 ; 6. Control character dispatch table.............................. 8 ; 7. Interrupt system tables....................................... 9 ; 8. Control character output control.............................. 10 ; 9. INITRM - Set special terminal/job status...................... 11 ; 10. RESTRM - Restore original TTY status.......................... 13 ; 11. GETTXT - Routine to return text buffer........................ 14 ; 12. Pagination routines........................................... 22 ; 13. Control character processing.................................. 24 ; 14. Special functions ; 14.1 Pagination and tab stop manipulation................. 34 ; 14.2 New file............................................. 43 ; 14.3 Deletes.............................................. 44 ; 14.4 Tabbing.............................................. 52 ; 14.5 Inserts.............................................. 53 ; 14.6 Search routines...................................... 60 ; 14.7 Pattern matching searches............................ 61 ; 14.8 String replacement................................... 63 ; 14.9 Positioning.......................................... 67 ; 15. Text movement routines ; 15.1 GETLIN............................................... 73 ; 15.2 RETLIN............................................... 74 ; 15.3 MOVPAR............................................... 76 ; 16. Justification routines........................................ 80 ; 17. Pagination routines ; 17.1 Routines to help auto-pagination..................... 88 ; 18. Show status command........................................... 90 ; 19. Toggle zero output command.................................... 93 ; 20. Special function control commands............................. 94 ; 21. Pattern matcher routines ; 21.1 Maktab............................................... 97 ; 21.2 Getpat............................................... 98 ; 21.3 Match................................................ 100 ; 22. Terminal control routines..................................... 102 ; 23. NXTWRD - Find the next word in the file....................... 103 ; 24. Adjustment routines ; 24.1 FILL................................................. 105 ; 24.2 EMPTY................................................ 112 ; 25. General subroutines........................................... 118 ; 26. Number input routines......................................... 126 ; ; (End of table of contents) Title VDT - Video Display Terminal Simulator Subttl Title page Search MACSYM,MONSYM,SYMBOL .Directive FLBLST Sall ;Version information -- used in loading WPSIM VEDIT==63 ; Edit number VDTEDT==:VEDIT ; Copy into an external ;Internal routines INTERN GETTXT,FILL,EMPTY,INITRM,RESTRM,UNFILL,MAKTAB,MATCH ;External storage EXTERN LINE,COL,BUF,MAXLIN,TOPLIN,HGHLIN,MAXCOL,BACKUP,SCHAR,SPARE EXTERN INDENT,TJFN,LENGTH,WIDTH,MINCOL,TIW,CCOC,TABS,INTBLK,SAVEP EXTERN PAGSIZ,SAVBUF,SAVNUM,LETHED,FLINK,PAT,CHRNUM,CHRCNT EXTERN NUMSCH,PAGNUM,PGHEAD,REPSTR,REPLEN,LSTSPC EXTERN HYPHEN,INTACS,INTSTK,EXPERT,XPNCOL,FUNCT,VALUE,PROG,CIPHER EXTERN MOD2,FILTAB,FSTLIN,INPLIN,OUTLIN,SCRVAL,CTRLCV,STRPAG,SHRINK EXTERN AUTOPG,HARDPG,CURRPG,BFRCNT,CHRPTR,JBUF,SFIRST,VT102 ;Description: ; ; VDT was written in August of 1981 by Douglas Bigelow at the ; Wesleyan Computing Center. VDT is a general purpose subroutine ; designed for use as a word processor simulator. ; Subttl Program flag definitions ;Define special SIN% jsys flag if it isn't in MONSYM Ifndef SI%TCC, ;Define time to wait for an error message to be seen HLDTIM==^D1500 ; 1.5 seconds ;Define a special error typing macro DEFINE TYPERR(STR),< JRST [HRROI A,[ASCIZ \STR\] JRST ERMSA]> ;Now define the flag accumulator bits BITPOS==0 ; **note: terminal flags must be in lh only SWITCH F.BHOM ; Terminal home is at bottom of screen SWITCH F.NWRP ; Terminal doesn't wrap left or up SWITCH F.ANSI ; Terminal follows ansi standard SWITCH F.CXBY ; Cursor is x before y SWITCH F.NFFD ; Terminal has no form feed SWITCH F.SPEF ; Terminal has special video effects SWITCH F.VT52 ; Terminal is a VT52 SWITCH F.V102 ; VT102 Terminal type ; **end of terminal flags ;More switches SWITCH F.TFAR ; Too far down - (too many lines) SWITCH F.FINI ; Finished SWITCH F.FMOV ; Forced move command in progress SWITCH F.FFCV ; Form feed conversion in progress SWITCH F.INDT ; Indent after refreshing SWITCH F.EMES ; Error message on screen SWITCH F.DSCR ; Downward scrolling move done SWITCH F.RPSH ; Repeating previous search SWITCH F.INSM ; Insert mode in effect SWITCH F.PMRK ; Page mark SWITCH F.NSIN ; New sin% jsys available SWITCH F.REPL ; Replacement string active SWITCH F.DGET ; Delete on get command SWITCH F.COPY ; Copy text SWITCH F.MOVE ; Move text SWITCH F.DELE ; Delete text SWITCH F.NEGR ; Negative retlin in effect SWITCH F.NBAK ; No backup on retlin SWITCH F.ZOUT ; Outputting to null: SWITCH F.TABC ; Tab conversion in progress SWITCH F.UPAR ; Up-arrow seen in control conversion mode SWITCH F.NOPG ; No change of the pagination mark is possible SWITCH F.IEOF ; Input end of file seen SWITCH F.DBSP ; Double spacing toggle for justification SWITCH F.DBIN ; Input text is double spaced SWITCH F.NELN ; Non-empty line found in justif routine SWITCH F.SPON ; Special effects on ;Now some spare storage used for auto-indent processing CRLFS: BYTE(7) 15,12,0,0,0 SPACES: asciz . . Subttl Terminal definitions ;Here we define the commands for all the terminals that we know about. DEFINE CL(X),<"X"-100> ALT==33 ; Define an escape NUL==0 ; And a null SP==40 ; And a space DEFINE TRMLST,< TRM (Viewpoint,4,,,,,) TRM (Datamedia,7,,,,,) TRM (VT100,20,,,,,) TRM (VT52,17,,,,,) > ;Now define the embedded 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 addr is ;the address of the string of characters. Eight bit characters are generated. 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 .SHFT==^D28 ; Initialize shift value IRP ,< ; Loop over all chars again WORD==WORD+<_.SHFT> ; Add new char into word .SHFT==.SHFT-8 ; Lessen shift by a char IFL .SHFT,< ; If the word is full EXP WORD ; Dump completed word of chars WORD==0 ; Reset the word .SHFT==^D28 ; And the shift value > > ; End of loop over chars IFN <.SHFT-^D29>,< ; See if any partial word left EXP WORD ; If so, dump it too > ],-CNT ; End literal and store count > ; End of ifn cnt conditional > ;Now define the tables that hold the terminal sequences DEFINE TRM(T.NAM,T.TYP,T.FLG,T.HOM,T.CEOL,T.CEOS,T.ADR),< EXP T.FLG+T.TYP> TRMTAB: TRMLST ; Generate the terminal list 0 ; End of list ;Now the home sequence table DEFINE TRM(T.NAM,T.TYP,T.FLG,T.HOM,T.CEOL,T.CEOS,T.ADR),< SEQ > HOMTAB: TRMLST ; Generate the home list 0 ; End of list ;Now the clear to end of line sequence table DEFINE TRM(T.NAM,T.TYP,T.FLG,T.HOM,T.CEOL,T.CEOS,T.ADR),< SEQ > CELTAB: TRMLST ; Generate the ceol list Z ;The clear to end of screen sequence table DEFINE TRM(T.NAM,T.TYP,T.FLG,T.HOM,T.CEOL,T.CEOS,T.ADR),< SEQ > CESTAB: TRMLST ; Generate the ceos list Z ;The absolute addressing sequence table DEFINE TRM(T.NAM,T.TYP,T.FLG,T.HOM,T.CEOL,T.CEOS,T.ADR),< SEQ > ADRTAB: TRMLST ; Generate the addressing list Z Subttl Control character dispatch table ;Any control character which may have a meaning to any of the supported ;terminals has a dispatch address where the character is handled. A ;cursor key is indicated by the sign bit being set, in which case the left ;half word also contains the terminal type for which the cursor key is ;appropriate. The dispatch table processing routine has the responsibility ;of resolving inter-terminal conflicts. ALL==400000 ; All terminals ADDS==400004 ; Viewpoints DATA==400007 ; Datamedias VT52==400017 ;GIGI and VT52 CCTAB: EXP R ; No meaning XWD ADDS,.HOM ; ^a - home on adds terminals EXP .FUN ; ^b - special functions EXP CTLC ; ^c - abort EXP DELETE ; ^d - delete functions EXP EXIT ; ^e - exit XWD ADDS,.RIG ; ^f - right on adds terminals EXP GETLIN ; ^g - get text XWD ALL,.LEF ; ^h - left on all terminals EXP .TAB ; ^i - tab on all terminals XWD ALL,.DWN ; ^j - down on all terminals EXP .SPEC ; ^k - special functions EXP .FFD ; ^l - clear on all terminals EXP .CR ; ^m - carriage return on all terminals EXP INSERT ; ^n - insert functions EXP RETLIN ; ^o - retrieve "gotten" text EXP POSIT ; ^p - position functions EXP R ; ^Q - unused EXP BAKTAB ; ^r - reverse tab EXP R ; ^S - unused EXP TRATAB ; ^t - transparent tab XWD ADDS,.LEF ; ^u - left on adds terminals EXP EVEN ; ^v - justify paragraph EXP PATMAT ; ^w - string search EXP SEARCH ; ^x - repeat search XWD DATA,.HOM ; ^y - home on a datamedia XWD ADDS,.UP ; ^z - up on an adds terminal EXP .ESC ; Esc - special handling XWD DATA,.RIG ; ^\ - right on a datamedia EXP DELEOL ; ^] - delete to end of line EXP R ; ^^ XWD DATA,.UP ; ^_ - up on a datamedia Subttl Interrupt system tables ;Level table LEVTAB: EXP INTBLK EXP INTBLK+1 EXP INTBLK+2 ;Channel table CHNTAB: 1,,CONC ; Channel zero, control-c BLOCK ^D35 ; No others at present ;Here to process a control-C. Ask the user if they really want to ;abort what they're doing. CONC: DMOVEM F,INTACS ; Save f and a MOVE A,[2,,INTACS+2] ; Load a blt pointer BLT A,INTACS+17 ; Store the acs MOVE P,[IOWD 50,INTSTK] ; Get a stack pointer CALL CONFRM ; Confirm the control-c JRST CONC.A ; Not really wanted CALL CLRSCN ; Clear the screen CALL RESTRM ; Restore normal mode TYPE <% Aborting -- type CONTINUE to resume, or REENTER to save your file> PUSH P,.JBREN## ; Save current reenter address MOVEI A,CONC.B ; Get reenter address MOVEM A,.JBREN## ; Save it HALTF% ; Quit ;If we're continued.. CALL INITRM ; Restore terminal CALL CLRSCN ; Clear screen ;; CALL .FFD ; Refresh it MOVEI A,.PRIIN ; Input MOVEI B,14 ; Form feed STI% ; Force a refresh ;Here if we never messed up the screen CONC.A: POP P,.JBREN## ; Restore old reenter address MOVE P,[INTACS,,0] ; Get blt pointer BLT P,P ; Restore all acs DEBRK% ; And dismiss the interrupt ;Here for a reenter CONC.B: POP P,.JBREN## ; Get old reenter address MOVE P,SAVEP ; Get old stack pointer RETSKP ; Return to output mode Subttl Control character output control ;Define the control characters that should be literally translated. ;Everything else doesn't echo, which prevents the terminal being affected ;by special effects that the program doesn't know about. DEFINE CCENB(X),< CCP1=0 CCP2=0 IRPC X,< .T="X"-100 .T=.T*2 IFL <.T-^D35>, IFG <.T-^D35>,> > > DEFINE CCLFT(X),< IRP X,< .T=X*2 IFL <.T-^D35>, IFG <.T-^D35>,> > > ;Now define the "action" characters CCENB (AFHJLMUYZ) ; The control characters CCLFT (<33,34,35,37>) ; And left-overs (non alphabetic) Subttl INITRM - Set special terminal/job status ;The terminal has to be carefully set up to run - exactly the correct ;control characters must echo in literal mode, and all others must not ;echo. The length and width must be zero. The terminal interrupt word ;must be cleared. Page mode must be disabled. And all standard parameters ;must be stored and restored at end of program. INITRM: MOVEI A,.CTTRM ; Controlling terminal GTTYP% ; Get our type SETZ P2, ; This will be the terminal pointer INI.A: SKIPN A,TRMTAB(P2) ; Get a terminal type NOERR (,EXIT) CAIE B,(A) ; Do we match right half? AOJA P2,INI.A ; No, try again HLLZ F,A ; Get the flags HRRZS A ; Isolate terminal type CAIE A,ADDS-ALL ; Is it a viewpoint? SETZM MOD2 ; No, so model2 switch is worthless MOVX A,GJ%SHT ; Short form HRROI B,ASC ; Tty device GTJFN% ; Get a jfn on it SSTERR (,EXIT) MOVX B,FLD(10,OF%BSZ)!OF%WR ; Write 8-bit bytes OPENF% ; Open the channel SSTERR (,EXIT) MOVEM A,TJFN ; Save the jfn MOVEI A,.FHJOB ; This job RTIW% ; Get current interrupt word MOVEM B,TIW ; Save it MOVX B,1B3 ; ^c only STIW% ; Set interrupt word ERJMP [TYPE <%Warning: Control-C's are not being trapped> JRST .+1] ; Type error and continue MOVEI A,.CTTRM ; Terminal RFCOC% ; Get current ccoc settings DMOVEM B,CCOC ; Save them MOVX B,CCP1 ; Control character output word one MOVX C,CCP2 ; And two SKPON F.ANSI!F.VT52 ; Does this terminal need escape? TRZ C,600000 ; No, so turn off escape SFCOC% ; Set it MOVEI B,.MORLW ; Line width MTOPR% ; Get current value MOVEM C,WIDTH ; And store MOVEI B,.MORLL ; Screen length MTOPR% MOVEM C,LENGTH ; Store current value MOVEI B,.MOSLW ; Set width function SETZ C, ; To zero MTOPR% MOVEI B,.MOSLL ; Set length MTOPR% ; Also to zero SKPON F.ANSI ; Are we ansi? JRST INI.B ; No, skip the next code MOVE A,TJFN ; Set alternate keypad mode MOVEI B,ALT ; By sending an = to the tty BOUT% ; Send an escape MOVEI B,"=" ; And an equal BOUT% ; Write it SKIPE VT102 ; Are we in VT102 mode? FLGON F.V102 ; Yes, set the flag ;Set up interrupts to intercept a ^C INI.B: MOVEI A,.FHSLF ; Our fork MOVE B,[LEVTAB,,CHNTAB] ; Tables SIR% ; Initialize MOVX B,1B0 ; Channel zero AIC% ; Activate it EIR% ; Enable system MOVE A,[3,,0] ; ^c to channel zero ATI% ; Activate terminal interrupt ERJMP .+1 ; Ignore the error this time RET ; Done Subttl RESTRM - Restore original TTY status RESTRM: SKPON F.ANSI ; Are we an ansi terminal? JRST RES.A ; No, skip the next code MOVE A,TJFN ; Reset the keypad mode by sending MOVEI B,ALT ; An BOUT% MOVEI B,">" ; And a ">" BOUT% RES.A: MOVE A,TJFN ; Get the terminal JFN CLOSF% ; Close the terminal JFCL ; Ignore errors MOVEI A,.FHJOB ; Our job MOVE B,TIW ; Get old interrupt word STIW% ; And set it ERJMP .+1 ; Ignore errors MOVEI A,.CTTRM ; This terminal DMOVE B,CCOC ; Get original ccoc settings SFCOC% ; Set them MOVEI B,.MOSLW ; Set width MOVE C,WIDTH ; To old value MTOPR% MOVEI B,.MOSLL ; Set length MOVE C,LENGTH ; To old value MTOPR% SETZ B, ; Current line position SFPOS% ; Now zero MOVE A,TJFN ; Terminal jfn CLOSF% ; Closed JFCL ; Ignore errors ;Disable the interrupt system MOVEI A,.FHSLF ; Our fork DIR% ; Disable interrupts SETZ B, ; No channels AIC% ; Now active MOVEI A,3 ; Terminal code 3 (^c) DTI% ; Deactivate terminal interrupt ERJMP .+1 ; Ignoring errors RET ; Done Subttl GETTXT - Routine to return text buffer ;GETTXT assumes that what shows on the screen is reflected by the buffer ;contents, and that the cursor is where LINE and COL say it is. Location ;MAXLIN contains the legal line limit for the input text. TOPLIN contains ;the current line that's at the top of the screen. Note that the line ;position to be used in cursor positioning, if such becomes necessary, is ;LINE modulo 24. Location BUF contains the address of the destination buffer. ;The input is terminated on two successive escapes. The failure return is ;taken if LINE exceeds MAXLIN. HGHLIN contains the number of the highest ;line seen. GETTXT: TRVAR ,IMFLG,BEGBUF,DIRECT,SHRVAL,DOUBLE,JCNT> SETZM DOUBLE ; Single spacing by default SETZM DIRECT ; Searching forward by default SKIPE PROG ; Programming mode? SETZM AUTOPG ; Yes, NO autopagination SETZM SHRVAL ; Clear shrink value MOVE T1,[POINT 7,BUF] ; Point to the buffer MOVEM T1,BEGBUF ; And save the pointer SETOM SLINE ; Clear it SETOM SCOL ; Clear it MOVEM P,SAVEP ; Save the stack pointer SETZM TOPLIN ; Top line counter MOVEI A,.CTTRM ; Terminal RFCOC% ; Get current ccoc settings DMOVEM B,CCSTRG ; Save them ;Initialize the screen FLGON F.INDT ; Indent after refresh CALL CLRSCN ; Clear the screen ; SKIPE SFIRST ; Are we in search-first mode? ; CALL PATMAT ; Yes, do a search first SKIPN SFIRST ; Search-first mode? CALL .FFD ; And initialize it CALL SETPTR ; Set up the pointer SKPON F.NSIN ; Do we have a new SIN% JSYS? CALL CHKSIN ; Not yet...make sure we don't ;This is the main character input loop GET.A: MOVE A,HGHLIN ; Get highest current line CAMLE A,MAXLIN ; Too high? RET ; Yes SKPON F.NSIN ; New SIN% jsys available? JRST GET.A2 ; Nope, do it the old way ;Attempt to read in a string of characters at once, for efficiency. We ; only do this if there are more than 2 characters left on the line to read, ; and only read to the first control character. SIN% must be modified for ; this function to work. MOVE C,MAXCOL ; Get column SUB C,COL ; Get characters left on line CAIG C,6 ; Line too short? JRST GET.A2 ; Yes, don't bother SUBI C,4 ; Don't go into check area MOVX D,SI%TCC ; Special JSYS flag BPM B,SPARE ; Point to a buffer MOVEI A,.PRIIN ; Principle input device MOVE T1,C ; Copy character count SIN% ; Read in the text SUBI T1,1(C) ; Get chars read minus one BPM B,SPARE ; Reset byte pointer JUMPLE T1,GET.A1 ; Only one char read, handle specially ADDM T1,COL ; Bump the column count MOVNS T1 ; Negate t1 ADDM T1,CHRCNT ; And bump character count ILDB A,B ; Get a byte IDPB A,P1 ; Deposit it AOJL T1,.-2 ; And loop until done ;Here for the last character on the line - might be control, handle differently GET.A1: ILDB A,B ; Get the character JRST GET.A3 ; Analyze it ;Here for regular character input, a byte at a time GET.A2: SOS CHRCNT ; Count down another character read PBIN% ; Get a character ;We can get here from escape handling routine, if we were forced to ; read in a pre-mature character. GET.A3: SETZM VALUE ; No numeric value assumed CAIN A,177 ; Is it a rubout? JRST GET.C ; Yes, handle it specially CAIGE A,SP ; Is it a control character? JRST GET.B ; Yes, handle it IDPB A,P1 ; Store the character CALL .RIG ; Move cursor right JUMPE T1,BREAK ; Look for line overflow CAMLE T1,MAXCOL ; Too far over? JRST BREAK ; Yes, correct the line CAMLE T1,MINCOL ; In the red zone? JRST CHECK ; Yes, look for a breaker JRST GET.A ; Next char ;Handle control characters here. Return from GETTXT when we get the non-skip ;return from CCTAB, which indicates end of input found. GET.B: SKIPL A,CCTAB(A) ; Get the dispatch code JRST GET.B1 ; Not a cursor char LDB T1,[POINT 9,A,17] ; Isolate type code JUMPE T1,GET.B1 ; All terminals if zero HRRZ T2,TRMTAB(P2) ; Get type of this terminal CAMN T1,T2 ; Same type? JRST GET.B1 ; Yes, execute the command JRST GET.A ; No, discard the command ;Here if the control character is legitimate GET.B1: FLGOFF F.NOPG ; Assume page mark will go away CALL (A) ; Control character dispatch address CALL SETPTR ; Set new pointer position SKPON F.NOPG ; If screen ok, dont do paging CALL SETPAG ; Display any page breaks on screen SKPON F.FINI ; Finished? JRST GET.A ; No, get next character CALL CLRSCN ; Clear the screen RETSKP ; And return ;Handle a rubout here. This gets treated as an actual delete, not as a ;backspace. It removes the character pointed to and shifts the line. GET.C: CALL DELCHR ; Delete a character CALL SETPTR ; Set the pointer up JRST GET.A ; Loop for more ; BREAK and CHECK - Routines to handle line breaking neatly ;Check -- if the character we just looked at was a space, break the line. CHECK: JUMPE A,CHE.A ; Neo-space? CAIE A,SP ; Or space? JRST GET.A ; No, return CHE.A: FLGON F.FMOV ; Forced move CALL .DWN ; Down a line CALL DOIND ; Do indentation JRST GET.A ; And continue ;Break - reverse and break the line at the first space we find. Go back only ;BACKUP characters before giving up, though. The double sequence at BRE.A ;probably looks odd, but reflect on the operation of the ADJBP instruction. BREAK: JUMPE A,CHE.A ; Check for neo-space CAIN A,SP ; Last one a space? JRST CHE.A ; Yes, let check handle it MOVE T2,BACKUP ; Get maximum backup MOVE T3,P1 ; Get copy of pointer ;Loop here going backwards through the line BRE.A: SETO T1, ; Set to minus one ADJBP T1,T3 ; Back up the pointer SOJ T2, ; Count back LDB T3,T1 ; Get a byte JUMPE T3,BRE.C ; Check for neo-space CAIN T3,SP ; Space? JRST BRE.C ; Yes, handle it JUMPL T2,BRE.E ; Check for exceeding backup value SETO T3, ; Now do same for other ac ADJBP T3,T1 ; Make copy and back it up one SOJ T2, ; Count back LDB T1,T3 ; Get the character JUMPE T1,BRE.B ; Check for neo-space CAIN T1,SP ; Space? JRST BRE.B ; Yes JUMPGE T2,BRE.A ; Loop if we haven't gone too far JRST BRE.E ; We have, break where we are ;We have a breaking spot. Pick up the characters we passed over and ;re-deposit them at the beginning of the next line. BRE.B: MOVE T1,T3 ; Get pointer in right ac BRE.C: SUB T2,BACKUP ; Get negative count of characters PUSH P,T2 ; Save it ADDB T2,COL ; Column where zeroing starts JUMPG T2,BRE.C1 ; Skip if normal count ADDI T2,^D80 ; We wrapped, back up to last line MOVEM T2,COL ; Store it SOS LINE ; Back up BRE.C1: PUSH P,T1 ; Save the pointer CALL CLREOL ; Blank out rest of line FLGON F.FMOV ; Forced move CALL .DWN ; Get to next line CALL DOIND ; Do indentation POP P,T1 ; Restore pointer POP P,T2 ; Restore counter MOVEI T3,SP ; Load a space ;Transfer from old line to new BRE.D: ILDB A,T1 ; Get a character DPB T3,T1 ; Overwrite it with a blank IDPB A,P1 ; Deposit it AOS COL ; Count it SKIPN A ; Is it a null? MOVEI A,SP ; Yes, that's a space PBOUT% ; And type it AOJL T2,BRE.D ; Loop as far as necessary JRST GET.A ; Done ;No breaking point is convenient, so break the line just where we are BRE.E: MOVNI T1,2 ; Load a minus two SKIPE HYPHEN ; Want a hyphen? MOVNI T1,1 ; Nope ADDM T1,COL ; Adjust the column ADJBP T1,P1 ; Copy the byte pointer PUSH P,T1 ; Save it HRROI A,[ASCIZ .- .] ; Two backspaces, etc SKIPE HYPHEN ; Do we want the hyphen? HRROI A,[ASCIZ . .] ; No, just break PSOUT% ; Repair the line FLGON F.FMOV ; Forced move in progress CALL .DWN ; Down a line CALL DOIND ; Indent it POP P,T1 ; Restore old pointer SKIPE HYPHEN ; Are we hyphenating? JRST BRE.E1 ; Nope, skip this ILDB A,T1 ; Get a byte MOVEI B,"-" ; Get a hyphen DPB B,T1 ; To replace it with IDPB A,P1 ; Move the char PBOUT% ; Type the char BRE.E1: ILDB A,T1 ; Get the next char MOVEI B,SP ; Load a space DPB B,T1 ; Overwrite the character PBOUT% ; Type that one too IDPB A,P1 ; Transfer complete CALL SETLC ; Set line and column JRST GET.A ; Done ;Special routine to position the text byte pointer according to the current ;line and column. SETPTR: STKVAR <> ; Temp storage DMOVEM T1,SAVT12 MOVE P1,LINE ; Get line number IMULI P1,20 ; Get word address for line beginning MOVE T1,COL ; Get column IDIVI T1,5 ; Get word within line block ADD P1,T1 ; Add to address ADD P1,BUF ; Add in buffer address HLL P1,PTRTAB(T2) ; Make proper byte pointer DMOVE T1,SAVT12 ; Restore acs RET ; Done ;Routine to position the line and column counters according to the current ;status of the byte pointer. SETLC: HLLZ T1,P1 ; Get byte pointer part HRRZ T2,P1 ; And address part SUB T2,BUF ; Remove offset IDIVI T2,20 ; Get line MOVEM T2,LINE ; Store it IMULI T3,5 ; Get start of column block HRLZI T2,-6 ; Counter for aobjn loop CAME T1,PTRTAB(T2) ; Check entries AOBJN T2,.-1 ; Loop through table ADDI T3,(T2) ; Add proper offset MOVEM T3,COL ; And store the column CAIGE T3,^D80 ; Too high? RET ; No SETZM COL ; Yes, we're on the next line AOS LINE ; So say so RET ; Done ;Byte pointer table PTRTAB::440700,,0 ; Point 7,0 350700,,0 ; Point 7,0,6 260700,,0 ; Point 7,0,13 170700,,0 ; Point 7,0,20 100700,,0 ; Point 7,0,27 010700,,0 ; Point 7,0,35 Subttl Pagination routines SETPAG: SKIPN AUTOPG ; Autopagination on? RET ; No, don't bother CALL CLRPG ; Clear any current marks SETO T1, ; Here we store loc of last page mark SKIPE HARDPG ; Any hard page marks yet? CALL FNDPAG ; Yes, find the nearest previous one JUMPGE T1,SETP.A ; Non-neg means value set MOVN T1,LETHED ; Otherwise use letterhead as count ADDI T1,4 ; Add in count of header ; Here we loop, adding the page size to the value in t1 (last mark) until ; we are >= the current top-of-screen line value. SETP.A: ADD T1,PAGSIZ ; Add the pagesize CAMGE T1,TOPLIN ; Are we greater than top-of-screen? JRST SETP.A ; No, keep incrementing SUB T1,TOPLIN ; Find the difference CAIL T1,^D23 ; Is it less than 24? RET ; No, so no page break on screen MOVE T2,T1 ; Store the marker value SKIPN HARDPG ; Any hard pages? JRST SETP.B ; No, so don't bother checking SKIPE B,T1 ; Copy it IMULI B,20 ; If non-zero, multiply by 20 ADD B,BUF ; Add buffer offset CALL FNDP.A ; Look for page break on screen JUMPGE T1,R ; Return if one found SETP.B: MOVEM T2,CURRPG ; Save current page marker ; Here we know there is a page break on the screen. Put it where it belongs: SETMRK: PUSH P,LINE ; Save the current line PUSH P,COL ; Save the column MOVEI A,^D79 ; The 79th col MOVEM A,COL ; Set it ADD T2,TOPLIN ; Find our loc on the screen MOVEM T2,LINE ; Set the line CALL FNDP.B ; See if there's a hard mark on screen JUMPLE T1,SETM.B ; If none, skip the next test MOVE B,LINE ; Recall the current line SUB B,TOPLIN ; Find it on the screen CAML B,T1 ; Is hard mark before soft one? JRST SETM.A ; Yes, don't write it then SETM.B: CALL SPCON ; Start the special effects CALL CURSOF ; Cursor off if possible CALL CURPOS ; Position the cursor MOVEI A,"P" ; Page marker PBOUT% ; Type it SETM.A: POP P,COL ; Reset the column POP P,LINE ; Reset the line CALL CURPOS ; Put the cursor back CALL SPCOFF ; Stop writing special characters CALL CURSON ; Restore cursor if off RET ; And return ; Here is the routine which erases the current page-mark from the screen: CLRPG: SKIPGE CURRPG ; Is there a current mark? RET ; No, just return PUSH P,LINE PUSH P,COL ; Save the current line and col MOVE A,CURRPG ; Recall where the mark is ADD A,TOPLIN ; Find the real line number MOVEM A,LINE ; Make it the line MOVEI A,^D79 ; 79 MOVEM A,COL ; Make it the current col CALL CURSOF ; Turn off cursor, if possible CALL CURPOS ; Move the cursor there MOVEI A," " ; Get a space PBOUT% ; Type it POP P,COL ; Restore the column POP P,LINE ; And the line CALL CURPOS ; Reset the cursor CALL CURSON ; Restore cursor if off SETOM CURRPG ; Clear the current page word RET ; And return ; Here is the FNDPAG routine. We search backward from the current line ; until we find a "~" as the first character of a line: FNDPAG: MOVE B,TOPLIN ; Recall the current line IMULI B,20 ; Make it a word counter ADD B,BUF ; Find it in the buffer MOVE T1,TOPLIN ; Where to start ; Now loop, looking for a "~" as the first character of a line FNDP.A: LDB A,[POINT 7,@B,6] ; Get the first character of the line CAIN A,"~" ; Is it a squiggle? RET ; Return with the counter SUBI B,20 ; Move to the previous line SOJGE T1,FNDP.A ; Loop for all lines RET ; And return ; Here to find if a hard page break is somewhere on the screen: FNDP.B: MOVE B,TOPLIN ; Recall the top of screen ADDI B,^D23 ; Find the current bottom line IMULI B,20 ; Make it a word ADD B,BUF ; Find it in the buffer MOVEI T1,^D23 ; We'll check up to 23 lines back JRST FNDP.A ; And look for the break Subttl Control character processing ;.HOM - Home the cursor. On an ADDS we go to the bottom left corner of ;the screen, but on any other terminal it's top left. .HOM: SETZM COL ; Column zero MOVE T1,TOPLIN ; Get top line MOVEM T1,LINE ; Make it current line SKPOFF F.BHOM ; On a bottom homing terminal? CALL HOMEUP ; An adds - really home it FLGOFF F.NOPG ; Don't change the page mark RET ; Return ;.LEF - Left cursor. This behaves differently on different terminals. .LEF: SKIPN T1,VALUE ; Repeat count? JRST .+3 ; No, regular MOVNS T1 ; Make count negative JRST POSM.C ; And dispatch FLGON F.NOPG ; So far, screen is ok SOSL T1,COL ; Reduce column RET ; Done - that was easy! FLGOFF F.NOPG ; But now screen might be bad SKPON F.NWRP!F.ANSI ; Non-wrapping terminal? JRST LEF.A ; Nope SETZM COL ; Yes, can't back past left edge RET ; Done LEF.A: MOVEI T1,^D79 ; Last column on previous line MOVEM T1,COL ; Store it CALL .UP ; Up one line RET ; Done ;.CR - Carriage return. Handled same on all terminals .CR: PBIN% ; Get the line feed FLGOFF F.DSCR ; No downward scrolling in effect SETZM COL ; Now at column zero CALL .DWN ; Go down a line TXZN F,F.DSCR ; Did .dwn set scrolling flag? SKIPLE INDENT ; Any indention? JRST DOIND ; Do the indentation RET ; Done ;.UP - Go up a line, watching for wraparound. .UP: SKIPN T1,VALUE ; Repeat count? JRST .+3 ; No, regular MOVNS T1 ; Make count negative JRST POSM.L ; And go do it SOS T1,LINE ; Back up a line SKIPE DOUBLE ; Double spacing? SOS T1,LINE ; Yes, two lines FLGON F.NOPG ; We left the page mark alone CAML T1,TOPLIN ; Backed up too far? JRST [SKIPE DOUBLE ; Double spacing? JRST CURPOS ; Yes, manual spacing RET] ; No, just return FLGOFF F.NOPG ; Might have changed the screen JUMPG T1,UP.B ; Hidden data, back up SETZM TOPLIN ; Set first line as top SETZM LINE CALL CURPOS ; Re-position cursor RET ; Done ;Here if we want to wrap backwards with more text available. UP.B: MOVE T1,TOPLIN ; Get present top SUB T1,SCRVAL ; Amount to scroll by SKIPGE T1 ; Don't go negative SETZ T1, CAMLE T1,LINE ; See if we're not back far enough MOVE T1,LINE ; We weren't, fix it MOVEM T1,TOPLIN ; Reset the top border CALL CLRSCN ; Clear screen CALL .FFD ; Refresh the screen RET ; And return ;Cursor right .RIG: SKIPE T1,VALUE ; Repeat count? JRST POSM.C ; Yes, handle that AOS T1,COL ; Bump the column FLGON F.NOPG ; Chance the screen is ok CAIGE T1,^D80 ; Wraparound? RET ; No FLGOFF F.NOPG ; Screen might be fudged, mark it SKPON F.ANSI!F.VT52 ; Ansi or vt52 mode? JRST RIG.A ; Nope, regular SOS T1,COL ; Yes, no wrapping available RET ; Done ;On a regular wrapping terminal RIG.A: SETZM COL ; Now on column zero CALL .DWN ; Cursor down one line SETZ T1, ; Return column RET ; Done ;.TAB - These are tricky to handle. The Viewpoints don't have hardware ;tabs, so for consistency on all terminals we set tabs to no echo mode and ;simulate them by spaces. .TAB: MOVEI A,SP ; Get a space TAB.A: IDPB A,P1 ; Deposit at least one PBOUT% ; And type it too AOS T1,COL ; Bump the column CAIL T1,^D80 ; Too far? JRST TAB.B ; Yes, new line ADJBP T1,[POINT 1,TABS] ; Get pointer to proper area ILDB T2,T1 ; Get the bit JUMPE T2,TAB.A ; Not set, keep going RET ; Done ;Here when we've tabbed too far and reached next line TAB.B: SETZM COL ; Yes, we're at left edge now CALL .DWN ; And down one line FLGOFF F.NOPG ; We could have blown floating mark RET ; Done ;Special routines to set and remove tab stops .REMTB: TDZA T1,T1 ; Clear t1 .SETTB: MOVEI T1,1 ; Set t1 SKIPN T2,COL ; Get column RET ; Don't mess with first tab ADJBP T2,[POINT 1,TABS] ; Get byte pointer IDPB T1,T2 ; Set or clear a tab RET ; Return ;.FFD - Form feed handling. The screen is now clear, so we should ;refresh it. .FFD: SETZM SFIRST ; Clear search mode SKPOFF F.NFFD ; No form feed? CALL CLRSCN ; Supply a clear screen SETZM CURRPG ; No page mark any more .FFD.B: MOVE T1,TOPLIN ; Get top of screen MOVEI T2,^D24 ; Amount to print ;Alternate entry from routines that don't want to start outputting at the top. FFD.A: PUSH P,BUF ; Save some parameters PUSH P,HGHLIN IMULI T1,20 ; Make into word offset ADDM T1,BUF ; Add to buf SOJ T2, ; Back up by one line MOVEM T2,HGHLIN ; Store for empty routine MOVEI A,SPARE ; Spare data buffer CALL EMPTY ; Translate the buffer SETZ T2, ; Wipe out the last crlf IDPB T2,T1 ; With a null POP P,HGHLIN POP P,BUF HRROI A,SPARE ; Get the buffer PSOUT% ; And type it TXZN F,F.INDT ; Should we indent? JRST CURPOS ; No, just return SKIPE COL ; Are we at left edge? JRST CURPOS ; No, so stay where we are MOVE T1,INDENT ; Get indent MOVEM T1,COL ; And set it JRST CURPOS ; Position and return ;CTLC - Control C handling. Here we just abort the program. If we're ;continued, we jump to .FFD to restore the screen to a known state. CTLC: CALL CLRSCN ; Clear the screen CALL RESTRM ; Restore normal terminal mode TYPE <% Aborting, type CONTINUE to recover> HALTF% ; Die CALL INITRM ; Back to special mode CALL CLRSCN ; Clear the screen CALL .FFD ; Reset the contents JRST GET.A ; And get next input ;Exit - leave the program EXIT: FLGON F.FINI ; Done RET ; Return ;.DWN - Go down one line. This gets a bit tricky, since the screen ;might scroll and we have to be aware of where the top line really is. .DWN: SKIPE T1,VALUE ; Repeat count? JRST POSM.L ; Yes, do it SKIPN DOUBLE ; Double spacing? IFSKP. ; Yes, add another line MOVEI A,12 ; Line feed PBOUT% ; Type it AOS A,LINE ; Add another line SUB A,TOPLIN ; Find out what line we're on CAIL A,^D24 ; Double scroll case? AOS TOPLIN ; Yes, account for it ENDIF. AOS A,LINE ; Down a line SUB A,TOPLIN ; How far down are we? FLGON F.NOPG ; We didn't move the window (yet) CAIGE A,^D24 ; Did we scroll? JRST DWN.A ; No, return after zeroing flags FLGOFF F.NOPG ; We moved it now MOVE A,LINE ; Get line again CAMLE A,HGHLIN ; Is there more text below? JRST DWN.B ; No MOVEI A,.PRIOU ; Output HRROI B,[BYTE (7) 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12] MOVN C,SCRVAL ; Number of lines down to go SKPON F.FMOV ; Forced move? AOJ C, ; No, so go one less SKIPE C ; Any more to go? SOUT% ; Yes MOVE T2,SCRVAL ; Get lines to refresh ADDM T2,TOPLIN ; Reflect new top line PUSH P,COL ; Save column SETZM COL ; Clear it CALL CURPOS ; Position POP P,COL ; Restore column MOVE T1,LINE ; Get line to start CALL FFD.A ; Do a partial refresh FLGON F.DSCR ; Downward scrolling in effect ;Make sure that the flag F.FMOV is zeroed no matter how we leave this ;routine, or else it can hang around to bother us later. DWN.A: FLGOFF F.FMOV ; Clear the flag MOVE A,LINE ; Get line back again CAMLE A,HGHLIN ; Did we set a new max? MOVEM A,HGHLIN ; Yes, set it JRST DWN.C ; * check for insert mode RET ; Done ;Check for a forced MOVE command - such as for a tab overflow. DWN.B: AOS TOPLIN ; Reflect new top line MOVEM A,HGHLIN ; Set new maximum line seen TXZN F,F.FMOV ; Forced move? RET ; No MOVEI A,12 ; Get a lf PBOUT% ; And go down a line ; RET ; Done ;* Check for insert mode DWN.C: SKPON F.INSM ; Insert mode? RET ; No, done MOVE A,IMFLG ; Get current line CAML A,LINE ; Are we within old limit? RET ; Yes, so we're done CALL INSLIN ; No, so add new line AOS IMFLG ; Bump the new line flag RET ; Done ;.ESC - Escape handling. Some special functions require an escape before ;the real command. Otherwise escapes get ignored unless we're on an ANSI ;mode terminal. ANSI terminals use escape sequences for cursor movement. ;** Update: escapes now mean beginning of number. .ESC: CALL GETNIN ; Get a number, w/o terminator SKIPN VALUE ; Don't erase an existing value MOVEM T1,VALUE ; Save it MOVE A,T2 ; Copy terminating byte JUMPE T1,ESC.0 ; Jump if no number CAIL A,SP ; A control char? JRST ESC.0 ; No SKIPLE T1,CCTAB(A) ; Get the dispatch address PBOUT% ; Must be echoed before dispatch JRST (T1) ; Cursor, go to it ;Here if not a numeric command ESC.0: CAIN A,"<" ; Open bracket? JRST ESC.D ; Yes CAIN A,">" ; Close bracket? JRST MOVPAR ; Yes, copy and delete text CAIN A,"O" ; A special function code? JRST ESC.C ; Yes, handle specially CAIE A,.CHDEL ; Don't echo a rubout PBOUT% ; Type the terminating byte SKPOFF F.VT52 ; Terminal a vt52? JRST ESC.1 ; Yes, skip the next tests SKPON F.ANSI ; Altmodes part of cursor movement? JRST GET.A3 ; No, analyze current character CAIE A,"[" ; A bracket? RET ; Nope, illegal MOVEI A,.PRIIN ; Input from TTY MOVEI C,12 ; Decimal NIN% ; Get number SETZ B, ; None there BKJFN% ; Back over terminator JFCL ; Can't PBIN% ; Get the terminator JUMPN B,RAINBO ; Number, probably a rainbow function ESC.1: CAIN A,"A" ; Code a = up JRST ESC.E ; Do it CAIN A,"B" ; Code b = down JRST ESC.A ; Handle it specially CAIN A,"C" ; Code c = right JRST .RIG ; Do it CAIN A,"D" ; Code d = left JRST .LEF ; Do it RET ; Ignore anything else ;Handle Rainbow function keys here RAINBO: CAIE A,"~" ; Function key? RET ; Nope, ignore JUMPLE B,R ; Can't be non-positive CAIL B,^D30 ; Or over 29 RET ; It was JRST @RAINTB(B) ; Go dispatch ;Dispatch table for Rainbow functions RAINTB: EXP R ; Nothing EXP PATMAT ;1 - find, ^W EXP INSMOD ;2 - insert, ^NI EXP DELWRD ;3 - delete, ^DW EXP ESC.D ;4 - select, $< EXP POSPRV ;5 - ^PP EXP POSNXT ;6 - ^PN Repeat ^D12, ;7 - 18 not used EXP CTLC ;19 - cancel, ^C^G EXP POSBEG ;20 - main screen, ^PB EXP EXIT ;21 - exit, ^E Repeat 6, ;22 - 27 not used EXP HLPMES ;28 - help, ^KH EXP R ;29 - do, not used ;We handle the down command specially because it doesn't scroll. Thus ;it must be different from the line feed, which does. ESC.A: MOVE T1,LINE ; Bump the line count SUB T1,TOPLIN ; Get distance from top MOVEI A,12 ; Load up a line feed CAIL T1,^D23 ; Tried to go off the screen? PBOUT% ; Force a cursor movement JRST .DWN ; And go to down routine ;Check for bumping the highest line ESC.B: MOVE T1,LINE ; Get current line CAMLE T1,HGHLIN ; Set new high water mark? MOVEM T1,HGHLIN ; Yes, say so RET ; Done ; Find out the sequence and handle the function code: ESC.C: SKPON F.ANSI ; An ansi terminal? RET ; No, ignore the sequence MOVEI A,"A" ; A dummy code to follow the escape PBOUT% ; Write it to the terminal to get ; Rid of the hanging CALL ICHAR1 ; Get the next character, no raise CAIE A,"S" ; Is it the home sequence? (pf4) JRST ESC.C1 ; Nope, find the function FLGON F.NOPG ; Left the screen alone SETZM COL ; Column zero MOVE T1,TOPLIN ; Get top line MOVEM T1,LINE ; Make it current line CALL HOMEUP ; And home the cursor RET ; Done ESC.C1: MOVEI T1,ESCMAX ; Get the conversion table size ESC.C2: HRRZ T2,ESCTAB(T1) ; Get a function code CAME A,T2 ; Match? IFSKP. ; Yes... HLRZ A,ESCTAB(T1) ; Get the corresponding function code MOVEI T1,FUNMAX ; Get the length of the other table JRST FUN.A ; And let the funct handler do the work ENDIF. ; ...yes SOJG T1,ESC.C2 ; No, look at the next entry TYPERR RET ; Return to caller ESCTAB: Z XWD "1","P" ; Pf1 XWD "2","Q" ; Pf2 XWD "3","R" ; Pf3 XWD "!","w" ; 7 XWD """","x" ; 8 XWD "#","y" ; 9 XWD "A","m" ; - XWD "B","t" ; 4 XWD "C","u" ; 5 XWD "D","v" ; 6 XWD "E","l" ; , XWD "F","q" ; 1 XWD "G","r" ; 2 XWD "H","s" ; 3 XWD "I","p" ; 0 XWD "J","n" ; . XWD "U","M" ; Enter ESCMAX==.-ESCTAB-1 ; Length of the table ;Mark a beginning position for the move command ESC.D: MOVE T1,LINE ; Get line MOVEM T1,SLINE ; Store it MOVE T1,COL ; Get col MOVEM T1,SCOL ; That too RET ; Done ;Move the cursor up. If we're at the top, then scroll the screen downwards ; and insert (scrval) lines. ESC.E: STKVAR ; Temporary variable MOVE A,LINE ; Get current line CAME A,TOPLIN ; Are we at the top? JRST .UP ; No, regular up MOVE B,SCRVAL ; Get current setting SUB A,B ; Too far? JUMPGE A,SCRL.A ; No ADD B,A ; Correct the change SETZ A, ; Cursor is homed JUMPLE B,R ; We're already at the top SCRL.A: MOVEM A,LINE ; Set line MOVEM A,TOPLIN ; And topline MOVEM B,SCRTMP ; Save amount to scroll SETOM CURRPG ; Say the old page marks are gone MOVE A,TJFN ; Get terminal jfn MOVE C,[SEQ] HLRZ B,C ; Copy string address HRLI B,441000 ; Make 8-bit pointer MOVN C,SCRTMP ; Get line count ASH C,1 ; Multiply by two SOUT% ; Type the string MOVEI A,15 ; Get a cr PBOUT% ; And home the line MOVE T1,LINE ; Get top line MOVE T2,SCRTMP ; Get line count CALL FFD.A ; Refresh that many lines MOVE A,LINE ; Get current line ADD A,SCRTMP ; Add offset SOJ A, ; Subtract for cursor movement SKIPE DOUBLE ; Double spacing set? SOJ A, ; Yes, one more line CAMGE A,TOPLIN ; Too far? MOVE A,TOPLIN ; Yes, correct it MOVEM A,LINE ; Restore new value for line JRST CURPOS ; And return Subttl Special functions -- Pagination and tab stop manipulation ;These are a class of functions that deserve control characters but ;don't have them. The ^K is followed by a letter code that specifies ;the action. .SPEC: CALL ICHAR ; Get a character CAIN A,"J" ; Join? JRST JOIN ; Yes CAIN A,"C" ; Center? JRST CENTER ; Yes CAIN A,"F" ; Flush right? JRST FLUSHR ; Yes CAIN A,"S" ; Set tabs? JRST .SETTB ; Yes CAIN A,"R" ; Remove tabs? JRST .REMTB ; Yes CAIN A,"B" ; Permanent page break? JRST PERMBK ; Yes CAIN A,"N" ; New file? JRST NEWFIL ; Yes CAIN A,"D" ; Togging double/single mode JRST DOUB ; Yes, toggle the mode CAIN A,"U" ; Unpaginate? JRST UNPAG ; Yes CAIN A,"I" ; Setting the indentation? JRST SETIND ; Yes CAIN A,"M" ; Setting maximum right margin? JRST SETMAX ; Yes CAIN A,"H" ; Heading set up? JRST SETHED ; Yes CAIN A,"?" ; Help command? JRST HLPMES ; Yes CAIN A,"L" ; List the functions? JRST LSTFUN ; Yes CAIN A,"V" ; Set scroll value? JRST SETSCR ; Yes CAIN A,"W" ; What command JRST SHOW ; Show the status CAIN A,"*" ; Search mode? SETOM SFIRST ; Yes, set the mode word CAIN A,"A" ; Adjust margins? JRST SHRMAR ; Yes ; CAIN A,"Z" ; Toggle zero output? ; JRST ZOUT ; Yes CAIE A,"P" ; Toggle pagination? RET ; No, none of the above, ignore it SETO A, ; Set A to be true SKIPE AUTOPG ; Are we paginating? SETZ A, ; We weren't, but we are now MOVEM A,AUTOPG ; Save the toggled flag RET ; None of the above ;Setind - reset the current line indentation SETIND: MOVE A,COL ; Get current column MOVEM A,INDENT ; Set as the new indent RET ; Done ;Setmax - reset the current maximum margin SETMAX: MOVE A,COL ; Get current column CAIGE A,14 ; Make sure it's not too small MOVEI A,14 ; Yes, change it CAILE A,^D78 ; Or too big MOVEI A,^D78 ; Yes, change it MOVEM A,MAXCOL ; Save it SUBI A,4 ; Now set mincol MOVEM A,MINCOL CAMLE A,BACKUP ; Larger than backup? MOVEM A,BACKUP ; Yes, can't be allowed RET ; And return ;Centering formfeed - center the current line on the page and refresh CNTFFD: SKIPE T1,VALUE ; Get repeat count JRST POSM.C ; It exists, char command SKPON F.NFFD ; If nffd terminal, ffd comes later CALL CLRSCN ; Supply a clear screen MOVE T1,LINE ; Get line SUBI T1,^D12 ; Get half a screen back SKIPGE T1 ; But don't go negative SETZ T1, MOVEM T1,TOPLIN ; New top of screen CALL .FFD ; Do a form feed RET ; And return ;Setscr -- set new scrolling parameter SETSCR: SKIPG A,VALUE ; Check the requested value TYPERR CAILE A,^D24 ; Too large? TYPERR MOVEM A,SCRVAL ; Store it RET ; And return ;Centering subroutine - Center the text on the current line CENTER: MOVE T1,MAXCOL ; Get right margin SKIPG T3,COL ; Get column RET ; Must be past zero SUB T1,T3 ; Get remaining space JUMPLE T1,R ; Must be some LSH T1,-1 ; Cut in half HRROI A,SPARE ; Point to spare buffer HRROI B,SPACES ; Source of spaces MOVNI C,^D79 ; Number to copy SOUT% ; Copy them SETZM COL ; Start at left margin CALL SETPTR ; Set up p1 MOVE A,T1 ; Get columns we're moving ADJBP A,[POINT 7,SPARE] ; Adjust the pointer MOVE B,P1 ; Source MOVN C,T3 ; Move (col) places SOUT% CALL CLREOL ; Clear the line MOVE A,P1 ; Beginning of line HRROI B,SPARE ; Source MOVNI C,^D79 ; Number to move SOUT% ; Copy the line, shifted MOVE A,P1 ; Where to start CALL TYPLIN ; Type it out MOVE T1,INDENT ; Indent position MOVEM T1,COL ; Set column FLGON F.FMOV ; Forced move in progress CALL .DWN ; Down to next line CALL CURPOS ; Position cursor RET ; Done ;Flush right subroutine - make current text flush right FLUSHR: MOVE T1,MAXCOL ; Get right margin SKIPG T3,COL ; Get column RET ; Must be past zero SUB T1,T3 ; Get remaining space JUMPLE T1,R ; Must be some HRROI A,SPARE ; Point to spare buffer HRROI B,SPACES ; Source of spaces MOVNI C,^D79 ; Number to copy SOUT% ; Copy them SETZM COL ; Start at left margin CALL SETPTR ; Set up p1 MOVE A,T1 ; Get columns we're moving ADJBP A,[POINT 7,SPARE] ; Adjust the pointer MOVE B,P1 ; Source MOVN C,T3 ; Move (col) places SOUT% CALL CLREOL ; Clear the line MOVE A,P1 ; Beginning of line HRROI B,SPARE ; Source MOVNI C,^D79 ; Number to move SOUT% ; Copy the line, shifted MOVE A,P1 ; Where to start CALL TYPLIN ; Type it out MOVE T1,INDENT ; Indent position MOVEM T1,COL ; Set column FLGON F.FMOV ; Forced move in progress CALL .DWN ; Down to next line CALL CURPOS ; Position cursor RET ; Done ;Join subroutine -- Join next line to current line JOIN: MOVE T1,MAXCOL ; Get maximum column SUB T1,COL ; Find spaces left JUMPLE T1,R ; Return if no space left PUSH P,P1 ; Preserve pointer MOVE T2,P1 ; Get pointer AOS LINE ; Go to next line SETZM COL ; Beginning of it CALL SETPTR ; Set a new pointer MOVE T3,MAXCOL ; Get max columns JOI.A: ILDB A,P1 ; Get a byte CAIE A,SP ; Discard spaces CAIN A,NUL ; And nulls SOJG T3,JOI.A ; Keep looking for a valid character JUMPE A,JOI.C ; None on line if zero CAMLE T1,T3 ; Check two counters MOVE T1,T3 ; Use only lesser of two CAIA ; Skip next ildb JOI.B: ILDB A,P1 ; Get a char IDPB A,T2 ; Deposit it SOJG T1,JOI.B ; Repeat until done JOI.C: POP P,P1 ; Restore old pointer CALL SETLC ; And restore old line and col CALL CLL.A ; Clear to end of line MOVE A,P1 ; Copy the pointer CALL TYPLIN ; Type this line over AOS LINE ; Get to next line CALL DELLN1 ; And delete it CALL DISPLA ; Display new remainder of screen RET ; And return ;SHRMAR routine -- shrink and expand margins SHRMAR: MOVE A,SHRVAL ;GET TOGGLE MOVE B,SHRINK ;GET SHRINK VALUE SKIPE A ;SHRINK FLAG SET? MOVNS B ;YES, NEGATE VALUE ADD B,INDENT ;ADD TO CURRENT INDENT SKIPGE B ;TOO SMALL? SETZ B, ;YES CAILE B,^D78 ;TOO LARGE? MOVEI B,^D78 ;YES MOVEM B,INDENT ;STORE NEW INDENT ;Now adjust the maximum SKIPE PROG ;PROGRAMMING? JRST SHRM.A ;YES, DON'T CHANGE RIGHT MARGIN MOVN B,SHRINK ;GET SHRINK VALUE SKIPE A ;FLAG SET? MOVNS B ;NEGATE IT ADD B,MAXCOL ;ADD TO CURRENT MAXIMUM SKIPGE B ;TOO SMALL? SETZ B, ;YES CAILE B,^D78 ;TOO LARGE? MOVEI B,^D78 ;YES MOVEM B,MAXCOL ;STORE NEW MAXCOL ;Now change the flag SHRM.A: XORI A,1 ;SET OR CLEAR MOVEM A,SHRVAL ;STORE IT RET ;AND RETURN ;HLPMES routine - display the help message ;Type out the help text, clear screen when a space is typed. HLPMES: CALL CLRSCN ; Clear the screen HRROI A,HLP..1 ; Get message PSOUT% ; Type it CALL ICHAR ; Get a continuation character CAIN A,SP ; Is it a space? JRST HLPTWO ; Yes, next page CALL CLRSCN ; Clear screen again JRST .FFD ; And refresh ;The help message HLP..1: ASCIZ \ +--------------------------( Command summary )--------------------------+ | | | ^P Position to: ^D Delete: | | C Centering refresh. C Character. (Same as RUBOUT) | | B Beginning of file. W Word. | | E End of file. L Line. | | L start of current Line. R Remainder of line. | | A Append to current line. E + ^G -- to End of file. | | N Next page (screen). F + ^G -- entire File. | | P Previous page (screen). | | W beginning of next Word. ^N iNsert: | | R Reverse word tab. (NIY) C Character. | | L Line. | | ^T Transparent tab. S Split line at cursor. | | ^R Reverse transparent tab. I continuous Insert mode. | ! F Function definition | | ^W Search for/replace a string. | | ^X Repeat last search/replace. ^E Exit from program. | | ^L Refresh the screen. | | ^V eVen text: | | P in Paragraph. (** Type space for more help, | | F in File. or to return to text **) | | | +----------------------------( Page one )-------------------------------+\ ;Page two of the help file ;Type out the help text, clear screen when a space is typed. HLPTWO: CALL CLRSCN ; Clear the screen HRROI A,HLP..2 ; Get message PSOUT% ; Type it CALL ICHAR ; Get a continuation character CAIN A,SP ; Is it a space? JRST HLPMES ; Yes, previous page CALL CLRSCN ; Clear screen again JRST .FFD ; And refresh ;The second page of the help file HLP..2: ASCIZ \ +--------------------------( Command summary )--------------------------+ | | | ^K Miscellaneous commands: ^K More miscellaneous: | | ? Type the help message. W What are tab/margin settings. | | V set Value for scrolling. S Set a tab stop. | | B insert a hard page Break N input a New file. | | R Remove a tab stop. | | ^G Get line(s) into text buffer: C Center text. | | M Move the lines (delete). F set text to Flush right. | | C Copy the lines (keep). I set new /INDENT value. | | M set new /MAXIMUM value | | $< Set beginning of text string. P toggle Pagination on and off | | $> Set end of text string: D toggle Double spacing | | M: move, C: copy, D: delete. U Remove hard page breaks | | R: return L List user defined functions | | H set up page Header. | | ^O Retrieve text in text buffer. J Join two lines together. | | | ! General note on numbers: any command may be preceeded by | | number -- this specifies a repeat count for the function. Cursor | | keys may also be used with a repeat count for fast movement. | | | | (** Type space for previous page, or to return to text **) | +----------------------------( Page two )-------------------------------+\ ;LSTFUN routine - list the user-defined functions LSTFUN: CALL CLRSCN ; Clear the screen SETZ T1, ; Set up a counter MOVEI D,FUNCT ; Point to the function list TYPE < User Defined Functions > ; Type a header LSTLOP: AOS T1 ; Increment the counter ADDI D,30 ; Increment our function word count SKIPN (D) ; Is there a function defined? JRST LSTL.A ; No, don't type anything TYPNCR ; Type an F CAIL T1,7 ; Is the function 1-6? IFSKP. ; Yes, just type the number NUMOUT T1,12 ; Type the number of the function ELSE. ; If not, type a letter MOVE A,T1 ; Get the number ADDI A,72 ; Make it the corresponding letter PBOUT% ; Type the byte ENDIF. ; End of typing a letter TYPNCR < [> ; Nice formating HRRO A,D ; Point to the function in question PSOUT% ; Write the function to the screen TYPE <]> ; And type a CRLF LSTL.A: CAIGE T1,FUNMAX ; Out of functions? JRST LSTLOP ; No, keep going TYPNCR < (Type any character to continue)> CALL ICHAR ; Yes, wait for a char to be input CALL CLRSCN ; Clear the screen JRST .FFD ; And then refresh the screen Subttl Special functions -- New file ;This routine clears the main buffer and inputs a new file, preserving ; the previous files switches. The routine is, unfortunately, WPSIM ; dependant. The new JFN is stored in external location IJFN. NEWFIL: CALL DELFIL ; Delete the file after confirmation SKIPLE HGHLIN ; Anything in the buffer? RET ; Yes, not confirmed CALL WRKSPC ; Get workspace set up CALL SPCON ; On with the lights MOVEI A,.CTTRM ; This terminal SETZ B, ; Zero the line and col SFPOS% ; Set the position TYPNCR ; Prompt MOVX A,GJ%SHT+GJ%OLD+GJ%FNS+GJ%CFM ; Old file MOVE B,[.PRIIN,,.PRIOU] ; Get info from terminal GTJFN% ; Get a jfn ERJMP NEWF.1 ; Can't HRRZM A,IJFN## ; Save the jfn MOVX B,FLD(7,OF%BSZ)!OF%RD ; Read access OPENF% ; Open it ERJMP NEWF.2 ; Can't MOVE A,IJFN## ; Jfn in a CALL FILL ; Get the file into the buffer ERJMP NEWF.3 ; Can't NEWF.A: CALL SPCOFF ; Off with the lights SETZM LINE ; Position to top of file SETZM COL SETZM TOPLIN ; Top of screen CALL CLRSCN ; Clear the screen CALL .FFD ; And display the screen RET ; And we're done ; Here to toggle between single and double space mode: DOUB: SETCMM DOUBLE ; Toggle double spacing RET ; And return ;Error returns NEWF.1: HRROI T1,ASC SKIPA ; Next NEWF.2: HRROI T1,ASC SKIPA ; Next NEWF.3: HRROI T1,ASC MOVEI A,.CTTRM ; This terminal RFPOS% ; Get position HRRZS B ; Isolate column JUMPLE B,NEWF.4 ; At the beginning TYPE ; At end of line -- type a cr NEWF.4: MOVE A,T1 ; Get string pointer PSOUT% ; Type it MOVEI A,HLDTIM ; Sleep time DISMS% ; Wait that long JRST NEWF.A ; And finish up Subttl Special functions -- Deletes ;Analyze the character following to determine whether to delete a word, line ;or to EOL or EOS. DELETE: CALL ICHAR ; Get a character CAIN A,"C" ; Character? JRST DELCHR ; Yes CAIN A,"W" ; Word? JRST DELWRD ; Yes CAIN A,"L" ; Line? JRST DELLIN ; Yes CAIN A,"R" ; Rest of line? JRST DELEOL ; Yes CAIN A,"E" ; To end of text? JRST DELEOS ; Yes CAIN A,"F" ; Delete whole file? JRST DELFIL ; Yes CAIN A,"B" ; Delete to beginning? JRST DELBEG ; Yes RET ; None of the above ;Routine to delete one character DELCHR: SKIPLE T1,VALUE ; Repeat value? JRST DELMCH ; Yes, do several MOVE A,P1 ; Get pointer MOVE C,COL ; Where are we? SUBI C,^D79 ; Get characters left on line ;Loop looking at rest of characters on line DELC.A: ILDB T1,A ; Get a character JUMPE T1,DELC.B ; Null is a space CAIE T1,SP ; Space JRST DELC.C ; Not a space ;Look for a line of all spaces remaining DELC.B: AOJL C,DELC.A ; Spaces only, keep going SOSGE COL ; End of line, back up JRST [AOS COL ; Too far, correct and return JRST DLC.B1] ; Back up to previous line CALL SETPTR ; Set pointer correctly IDPB T1,P1 ; Deposit a space MOVEI A,10 ; Get a backspace PBOUT% ; Type it CALL CLL.A ; Clear to eol RET ; Done ;Move back a line DLC.B1: SOS T1,LINE ; Back up SKIPE DOUBLE ; Double spacing? SOS T1,LINE ; Yes, double it FLGON F.NOPG ; No page mark manipulation CAML T1,TOPLIN ; Backing past top of screen? JRST POSELN ; Nope, position to eol JUMPG T1,DLC.B2 ; Hidden data? SETZM LINE ; No, set line zero SETZM TOPLIN ; Same for top of screen JRST POSELN ; Position cursor DLC.B2: CALL UP.B ; Back the cursor back a segment JRST POSELN ; Too much cursor manipulation... ;Routine to delete to beginning of file DELBEG: MOVE T1,COL ; Get column MOVE T2,INDENT ; Get indent SUB T1,T2 ; Get difference JUMPL T1,R ; Don't do it if beyond indent MOVEM T2,COL ; Set new column CALL SETPTR ; Set the pointer JRST DELMCH ; And remove the space ;This line gets a regular deletion of a character at the cursor DELC.C: SKPON F.V102 ; Are we a VT102 terminal? CALL CLL.A ; No, clear to end of line MOVE A,P1 ; Destination MOVEI B,1 ; Source is destination+1 ADJBP B,P1 ; So get it MOVE C,COL ; Get column SUBI C,^D79 ; Get minus columns left SKIPE C ; Don't let it be zero SOUT% ; Move in SKPOFF F.V102 ; Are we VT102? JRST DELC.D ; Yes, delete a char and return MOVEI D,SP ; No, get a space IDPB D,A ; And tack it on MOVE A,P1 ; Get pointer CALL TYPLIN ; Type the line CALL CURPOS ; Get cursor back RET ; Done ;Here to delete characters on a VT102 terminal: DELC.D: SKIPN T1,VALUE ; Do we have a count? MOVEI T1,1 ; No, make it a 1 DELC.E: MOVE A,TJFN ; The jfn of the terminal MOVEI B,ALT ; An escape BOUT% ; Write it MOVEI B,"[" ; A bracket BOUT% ; Write it MOVE B,T1 ; Get the repeat count CAILE B,^D80 ; Too many? MOVEI B,^D80 ; Yes, reduce to a reasonable number HRRZI C,12 ; Decimal, no column count NOUT% ; Write the number DBLERR (Nout Failed,CONT) MOVE A,TJFN ; To the terminal again MOVEI B,"P" ; A p to terminate BOUT% ; Write it RET ; And return to caller ;Here to delete many characters DELMCH: MOVE T3,T1 ; Copy number ADD T1,COL ; Get column that would put us at CAIG T1,^D79 ; Too far? JRST DELM.A ; Nope SUBI T1,^D79 ; Get distance over SUB T3,T1 ; Modify value SKIPG T3 ; Still legal? TYPERR DELM.A: PUSH P,T3 ; Save the number CALL SHIFT ; Shift line by (t3) chars POP P,T1 ; Restore count SKPOFF F.V102 ; Are we a VT102 terminal? JRST DELC.E ; Yes, go delete (t1) characters CALL CLREOL ; Clear line MOVE A,P1 ; Copy pointer CALL TYPLIN ; Type rest of line CALL CURPOS ; Position RET ; And return ;Delete line routines - remove the line at the cursor DELLIN: SKIPLE T4,VALUE ; Repeat count? IFSKP. ; No, do one line MOVEI T4,1 ; Load one SKIPE DOUBLE ; Double spacing? LSH T4,1 ; Yes, double to two lines ENDIF. DELN.A: PUSH P,T4 ; Save the delete count CALL DELLN1 ; Delete 1 line SOJG T4,.-1 ; Repeat as far as necessary POP P,T4 ; Retreive the line count CAIG T4,^D23 ; Too many lines? SKPON F.V102 ; Or a VT102 terminal? JRST DISPLA ; Either one...display and ret ; Here if we have a VT102 terminal...do a fancy line delete and redisplay MOVE A,TJFN ; Get the tty jfn MOVEI B,ALT ; An esc BOUT% ; Send it MOVEI B,"[" BOUT% ; Send a bracket MOVE A,TJFN ; Point at the destination MOVE B,T4 ; Get the number to output CAILE B,^D24 ; Too many? MOVEI B,^D24 ; Yes, reduce to a reasonable number HRRZI C,12 ; A base 10 number NOUT% ; Translate it into ascii DBLERR (Nout failed,CONT) MOVE A,TJFN ; Recall the terminal jfn MOVEI B,"M" ; Delete line code BOUT% ; Send it PUSH P,LINE ; Save the current line number MOVE T3,TOPLIN ; Get the top of screen ADDI T3,^D24 ; Find the bottom line SUB T3,T4 ; Find t4 lines form the bottom CAML T3,LINE ; Further along in file? MOVEM T3,LINE ; Pretend this is the current line CALL DISPLA ; Redisplay here POP P,LINE ; Recall the current line CALL CURPOS ; Position the cursor RET ; And return ;This is the routine to delete one line without updating the display DELLN1: MOVE A,LINE ; Get line IMULI A,20 ; Get word starting line ADD A,BUF ; Point to text HRLS A ; Put in left half ADD A,[20,,0] ; Make "from" higher than "to" SOS B,HGHLIN ; Lower highest line CAMGE B,LINE ; Must not delete too far AOS HGHLIN ; So if we did, bump hghlin back up IMULI B,20 ; Point to new highest line ADD B,BUF ; Inside buffer BLT A,17(B) ; Shift everything MOVE A,SPACES ; Get some spaces MOVEM A,20(B) ; Store in last line HRLI A,20(B) ; Set up new blt pointer HRRI A,21(B) BLT A,37(B) ; Clear new highest line RET ; And return ;DELEOL - delete to end of line routine. DELEOL: CALL TXTEOL ; Remove text to end of line CALL CLREOL ; Clear on screen RET ; Done ;DELEOS - Delete from cursor to end of text DELEOS: CALL CONFRM ; Make sure that's what's wanted RET ; It wasn't CALL TXTEOL ; Remove text trailing this line MOVE T1,LINE ; Get current line MOVE T2,HGHLIN ; Get highest line CAML T1,T2 ; Are we at the top? JRST CLREOS ; Yes, nothing more to remove MOVEM T1,HGHLIN ; New highest line AOJ T1, ; Start at next IMULI T1,20 ; Convert to word value ADD T1,BUF ; Make into address HRLS T1 ; Get into left half SUB T1,[1,,0] ; Point back into cleared area IMULI T2,20 ; Convert high line to word address ADD T2,BUF ; Make it an address BLT T1,17(T2) ; Propogate the spaces CALL CLREOS ; Clear to end of screen RET ; And return ;TXTEOL - Remove the text on the current line trailing the cursor. TXTEOL: MOVE A,P1 ; Get pointer HRROI B,SPACES ; Space source MOVNI C,^D79 ; Get line length ADD C,COL ; Left after cursor SKIPE C ; Don't let it be zero SOUT% ; Clear with spaces MOVEI B,SP ; Get a space IDPB B,A ; And wipe out that trailing null RET ; Done ;Delete a word. Erases the word either at or following the cursor, ;plus the trailing spaces. DELWRD: CALL NXTWRD ; Get coordinates of next word JRST DLW.A ; No word following MOVEM T1,COL ; Where it starts CALL SETPTR ; Set the pointer to it CALL SHIFT ; Shift the line over by (t3) CALL CLREOL ; Clear to end of line MOVE A,P1 ; Get pointer CALL TYPLIN ; Type the line CALL CURPOS ; Get cursor back RET ; Done ;Here to back up a character and try again DLW.A: SOSGE COL ;TRY BACKING UP JRST [SETZM COL ;CAN'T, WE'RE AT BEGINNING JRST CURPOS] ;FIX UP CURSOR CALL SETPTR ;SET UP THE POINTER JRST DELWRD ;TRY AGAIN ;Shift subroutine -- shift the line over (T3) places to the left, filling ;in trailing blanks on the right. SHIFT: MOVE A,P1 ; Destination MOVE B,T3 ; Number of spaces to delete ADJBP B,P1 ; Now points to source MOVE C,COL ; Get column ADD C,T3 ; Add field width SUBI C,^D80 ; Get minus columns left SKIPE C ; Don't let it be zero SOUT% ; Move in MOVEI D,SP ; Get a space IDPB D,A ; And tack it on SOJG T3,.-1 ; Loop for number of deleted spaces RET ; Done ;Function F - delete whole file DELFIL: CALL CONFRM ; Confirm the request RET ; Not really meant CALL CLRSCN ; Clear the screen SETZM TOPLIN ; Start at line zero SETZM LINE ; We're at home position MOVE T1,INDENT ; Get indention MOVEM T1,COL ; Set it CALL CURPOS ; Position there MOVE T1,SPACES ; Get some spaces MOVEM T1,@BUF ; Clear first word MOVE T3,HGHLIN ; Get highest line seen IMULI T3,20 ; Get number of words ADDI T3,17 ; Add another line's worth ADD T3,BUF ; Add in address of buffer HRL T2,BUF ; Get buffer start HRR T2,BUF ; In both halves AOJ T2, ; Bump right hand side BLT T2,(T3) ; Clear whole storage block SETZM HGHLIN ; Highest line we've seen RET ; Done Subttl Special functions -- Tabbing ;Transparent tabs - non destructive as they move. TRATAB: FLGOFF F.NOPG ; Doesn't need resetting of page mark AOS T1,COL ; Bump the column CAIL T1,^D80 ; Too far? JRST TRA.A ; Yes, down a line ADJBP T1,[POINT 1,TABS] ; Get pointer to proper area ILDB T2,T1 ; Get the bit JUMPE T2,TRATAB ; Not set, keep going JRST TRA.B ; Done, position and return ;Here we adjust for a new line TRA.A: SETZM COL ; Zero the column FLGON F.FMOV ; Forced move in progress CALL .DWN ; Down a line ;Now get the cursor where we want it TRA.B: CALL CURPOS ; Position it RET ; And return ;Backtabs - non-destructive tabs backwards to previous tab stop. BAKTAB: SOS T1,COL ; Backup the cursor FLGOFF F.NOPG ; Doesn't need resetting of page mark JUMPL T1,BAK.A ; Too far? ADJBP T1,[POINT 1,TABS] ; Get pointer to proper bit ILDB T2,T1 ; Get it JUMPE T2,BAKTAB ; No set, keep going JRST BAK.B ; Found one ;Here when we've backed up a line BAK.A: MOVEI T1,^D79 ; Last column MOVEM T1,COL ; Set it CALL .UP ; Tell program we went up a line JRST BAKTAB ; Keep trying on this new line ;Now get the cursor where we want it BAK.B: CALL CURPOS ; Position it RET ; And return Subttl Special functions -- Inserts ;Insert either a line or an unknown number of characters. If the latter, ;we break the current line and put the remainder on the next line. ;Or, insert a function definition into the function block. INSERT: CALL ICHAR ; Get the specifier CAIN A,"L" ; Line? JRST INSLIN ; Yes CAIN A,"C" ; Char? JRST INSCHR ; Yes CAIN A,"S" ; Split? JRST INSPLT ; Yes CAIN A,"I" ; * insert mode to stick? JRST INSMOD ; * yes CAIN A,"F" ; Function definition? JRST INSFUN ; Yes RET ; No good ;Here to insert a whole line INSLIN: SKIPLE T2,VALUE ; Repeat count? IFSKP. ; No, do one line MOVEI T2,1 ; Load one SKIPE DOUBLE ; Double spacing? LSH T2,1 ; Yes, double to two lines ENDIF. MOVE T1,LINE ; Insert the line here CALL ILINE ; Insert line(s) SKPON F.V102 ; A VT102 terminal? JRST DISPLA ; No, now display ; Here for VT102 terminals. Do a fancy insert. PUSH P,LINE ; Save the current line MOVEM T1,LINE ; Set the new line for insert CALL CURPOS ; Move the cursor there MOVE A,TJFN ; Get the tty jfn MOVEI B,ALT ; An esc BOUT% ; Send it MOVEI B,"[" BOUT% ; Send a bracket MOVE A,TJFN ; Point at the destination MOVE B,T2 ; Get the number to output CAILE B,^D24 ; Too many? MOVEI B,^D24 ; Yes, reduce to a reasonable number HRRZI C,12 ; A base 10 number NOUT% ; Translate it into ascii DBLERR (Nout failed,CONT) MOVE A,TJFN ; Recall the terminal jfn MOVEI B,"L" ; Insert line code BOUT% ; Send it POP P,LINE ; Restore the old line loc CALL CURPOS ; Position the cursor RET ; And return ;Here to toggle insert mode INSMOD: TXCE F,F.INSM ; * on or off? JRST INM.A ; Off CALL LINACT ; Active line? IFSKP. ; Yes, do the following CALL INLN1 ; Insert 1 line CALL INS.B ; And do a split ENDIF. ; Done MOVE A,LINE ; Save current line MOVEM A,IMFLG ; For later use RET ; Done ;Here when we're turning insert mode off - justify the code now INM.A: PUSH P,LINE ; Save current line JRST EVE.A ; And even current paragraph ; Subroutine to insert one or more lines into the workspace. ; Call with T1 containing line number in front of which new lines are to ; be inserted. T2 contains the number of lines to insert. The inserted ; lines will be zeroed before returning. ; Entry point if double spacing is to be considered a factor: ILINED: SKIPE DOUBLE ; Double spacing? LSH T2,1 ; Yes, double the # of lines ; Entry point for straight single spacing insertion: ILINE: DMOVE B,T1 ; Copy the args SOS B ; Adjust the location argument MOVE A,HGHLIN ; Top line of file SUB A,B ; Get number of lines to insert IMUL A,[-20] ; Make a neg number of words MOVE B,HGHLIN ; Get highest line LSH B,4 ; Multiply by 20 to get words ADD B,BUF ; Add buffer address ADDI B,17 ; Last word of the line IMULI C,20 ; Number of words to insert ADD C,B ; New destination EXTEND A,[XBLT] ; Do a backwards blt ADDM T2,HGHLIN ; Set the new highest line ;Now clear the area vacated DMOVE A,T1 ; Copy values again LSH A,4 ; Word number of starting area ADD A,BUF ; Address SETZM (A) ; Clear first word HRLS A ; Put into left half AOJ A, ; Bump right half LSH B,4 ; Number of words to clear ADDI B,(A) ; Add location to start at BLT A,-2(B) ; And move words until we get there RET ; Done ; Here to insert a line, ignoring the single/double spacing status: INLN1: PUSH P,T2 ; Save the current t2 PUSH P,T1 ; Save t1 too MOVE T1,LINE ; Insert the line where we are AOS T1 ; But after the current line MOVEI T2,1 ; Insert 1 line CALL ILINE ; Go do it POP P,T1 ; Retore t1 POP P,T2 ; And t2 RET ; And return ;Insert a line after the current line, or 2 if double spacing: INLN2: PUSH P,T2 ; Save the current t2 PUSH P,T1 ; Save t1 too MOVE T1,LINE ; Insert the line where we are AOS T1 ; But after the current line MOVEI T2,1 ; Insert 1 line CALL ILINED ; Go do it POP P,T1 ; Retore t1 POP P,T2 ; And t2 RET ; And return ;Here to insert a partial line INSPLT: CALL INLN1 ; Insert a line INS.B: CALL SPLIT ; Split this line SKIPE DOUBLE ; Double spacing? CALL INLN1 ; Yes, insert one line PUSH P,COL ; Save proper column SETZM COL ; Reset it CALL DISPLA ; Display the screen changes POP P,COL ; Restore proper column JRST CURPOS ; And get there ;Split subroutine. Split the current line at the cursor, but don't update. SPLIT: SKIPN PROG ; Programming? CALL NXTWRD ; Find beginning of word JRST SPL.A ; Split the line here MOVEM T1,COL ; Use that column to start CALL SETPTR ; And reset the pointer SPL.A: PUSH P,P1 ; Save current pointer AOS LINE ; Bump the line PUSH P,COL ; Save column SETZM COL ; Zero the column CALL SETPTR ; Reset the pointer MOVE A,INDENT ; Get indent POP P,B ; Restore column CAMLE A,B ; Beyond current column? SETZ A, ; No, so start on the margin ADJBP A,P1 ; Point to proper place on this line MOVE P1,(P) ; Get proper value of p1 back CALL SETLC ; Reset old line and column MOVE B,P1 ; Get source MOVNI C,^D79 ; Find out how many.. ADD C,COL ; ..characters to send SKIPGE C ; Check for no transfer SOUT% ; Send them ILDB T2,B ; Get one more byte IDPB T2,A ; And insert it MOVE A,P1 ; Get pointer HRROI B,SPACES ; What to write MOVNI C,^D79 ; Number of spaces ADD C,COL ; Left after text SKIPGE C ; Don't transfer if nothing to do SOUT% ; Fill in all but last POP P,P1 ; Restore old pointer RET ; Done ;Here to insert characters. Put in a blank and shift the rest of the ;line to the right. Characters shifted out of last position are lost. INSCHR: SKIPG T1,VALUE ; Multiple? MOVEI T1,1 ; No, only one MOVE T3,P1 ; Store pointer CALL MAKSPC ; Make some space TYPERR CALL CLREOL ; Clear to end of line MOVE A,T3 ; Retrieve old pointer CALL TYPLIN ; Type rest of line CALL CURPOS ; Position cursor RET ; And return ;Makespace routine -- insert several characters MAKSPC: MOVE A,T1 ; Copy number ADD A,COL ; Add to current column SUB A,MAXCOL ; Check against right edge SKIPLE A ; Past it? RET ; Yes, give error return MOVE C,COL ; Get column SUBI C,^D79 ; Get remainder of line HRROI A,SPARE ; Point to spare buffer MOVE B,P1 ; Get text pointer SKIPGE C ; Only if characters to transfer SOUT% ; Transfer the data MOVE A,T1 ; Get space count MOVEI T4,SP ; Get a space IDPB T4,P1 ; Store it where we are SOJG A,.-1 ; Loop for all spaces MOVE A,P1 ; Where to put the remainder MOVE B,[POINT 7,SPARE] ; Source MOVE C,COL ; Get column SUB C,MAXCOL ; Remainder of line ADDI C,1(T1) ; Minus number of spaces SKIPGE C ; Check for no transfer SOUT% JUMPG C,.+3 ; Maybe we shouldn't type anything ILDB T4,B ; Last one IDPB T4,A ; Overwrites the null RETSKP ; Done ;Here we allow the user to assign a function to a function key. INSFUN: CALL WRKSPC ; Get some workspace CALL SPCON ; Special effects HRROI A,ASC ; Prompt CALL GETSTU ; Get a string MOVE B,[POINT 7,SPARE] ; Point to it ILDB A,B ; Get the name ILDB C,B ; Get the next byte JUMPN C,INSF.B ; If not a null, error SUBI A,60 ; Make it useable JUMPLE A,INSF.B ; Zero or less...illegal CAIG A,6 ; Was it a proper number? JRST INSF.A ; Yes CAIG A,20 ; Improper number? JRST INSF.B ; Yes CAILE A,32 ; Too big a letter? JRST INSF.B ; Yes SUBI A,12 ; Good letter, make it a number >11 ;Here for a proper function name INSF.A: IMULI A,30 ; Find the index into function storage MOVEM A,T4 ; And save it CALL WRKSPC ; Beginining of work space HRROI A,ASC ; Prompt CALL GETSTR ; Get the string MOVE A,[POINT 7,SPARE] ; Point to the string MOVE B,[POINT 7,0] ; Destination HRRI B,FUNCT(T4) ILDB C,A ; Get a byte IDPB C,B ; No, write it out JUMPE C,.+2 ; Zero? done. JRST .-3 ; Loop ;Here when done CALL SPCOFF ; Of with the lights CALL CLRWRK ; Clear the workspace RET ; And we're done ;Here for an illegal function name INSF.B: TYPNCR <% Illegal function name> MOVEI A,HLDTIM ; Waiting time DISMS% ; Sleep long enough to see it CALL SPCOFF ; Effects off CALL CLRWRK ; Clear the workspace RET ; Error and return Subttl Special functions -- Search routines ;This routine searches for the last string found by a ^W search, or for ;an "@" if this is the first search. SEARCH: FLGOFF F.NOPG ; Doesn't need resetting of page mark FLGON F.RPSH ; Say we're repeating previous search SKPOFF F.REPL ; Replacement? JRST REPLA ; Yes, do that SKIPE CHRNUM ; Any characters? JRST PMATCH ; Yes, repeat last search MOVEI A,"@" ; Get a char MOVEM A,PAT+1 ; Store it MOVEI T3,1 ; One character MOVEM T3,CHRNUM ; Store it CALL MAKTAB ; Make the table JRST PMATCH ; And match it Subttl Special functions -- Pattern matching searches ;This routine uses the Knuth-Morris-Pratt algorithm. PATMAT: FLGOFF F.NOPG ; Doesn't need resetting of page mark MOVE A,VALUE ; Recall the repeat value MOVEM A,DIRECT ; Save it as the direction were heading MOVE T1,[PAT,,PAT+1] ; Get a blt pointer FLGOFF F.REPL!F.RPSH ; Not a replacement, not repeating SETZM PAT ; Clear a word BLT T1,FLINK+120 ; Clear to end CALL GETPAT ; Get the pattern CALL MAKTAB ; Make the pattern matcher SKPOFF F.REPL ; Replacement? JRST REPLA ; Yes, proceed ;Alternate entry point from SEARCH PMATCH: CALL MATCH ; Find a match IFNSK. ; Not found SKIPLE VALUE ; Are we repeating? JRST PATM.Z ; Yes, so reset cursor JRST PATM.C ; No, so cursor hasn't moved ENDIF. SOSLE VALUE ; Count down number of searches JRST PMATCH ; More to do PATM.Z: MOVE T1,LINE ; Get current line SUB T1,TOPLIN ; Get top of screen SKIPL DIRECT ; Were we searching backward? IFSKP. ; Yes... SKIPL T1 ; Are we still on the screen? JRST PATM.A ; No, so dont refresh ELSE. ; No... CAIGE T1,^D24 ; Are we off the screen? JRST PATM.A ; No, so just repair last lines ENDIF. ; End of conditional CALL SPCOFF ; Turn off special effects MOVE T1,LINE ; Get current line SUBI T1,^D12 ; Split a screen SKIPGE T1 ; Are we still in the file? SETZ T1, ; No, set the top of screen MOVEM T1,TOPLIN ; Store new screen top CALL CLRSCN ; Clear SKIPN SFIRST ; Just starting? CALLRET .FFD ; No, refresh screen and return CALLRET TYPLN1 ; Yes, just type the line and return ;Here when we're still on the current screen. Just repair last lines, which ;were used to hold the pattern we matched. PATM.A: SKPON F.RPSH ; Repeating previous search? JRST PATM.B ; No, jump ahead SKIPN SFIRST ; Searching at first? JRST CURPOS ; No, so nothing to repair CALLRET TYPLN1 ; Yes, type the line and ret PATM.B: CALL SPCOFF ; Turn off special effects CALL CLRWRK ; Clear the work space SKIPN SFIRST ; Searching at first? RET ; No, just return CALLRET TYPLN1 ; Yes, type the line and ret ;Here if we didn't find a string PATM.C: SKIPN EXPERT ; Are we expert? JRST PTM.C1 ; No, type message SKIPE SFIRST ; Searching at first? CALLRET TYPLN1 ; Yes, type the line and return SKPOFF F.RPSH ; Repeat search? RET ; Yes, so no workspace to clear JRST PATM.B ; No, so must clear workspace PTM.C1: CALL WRKSPC ; Clear a message area CALL SPCON ; On with the effects TYPNCR <% Search string was not found> MOVEI A,HLDTIM ; Time to wait DISMS% ; Sleep JRST PATM.B ; And quit Subttl Special functions -- String replacement ;This function implements search and replace REPLA: STKVAR ; Get a temp variable CALL MATCH ; Match up the string JRST PATM.C ; Can't MOVN T3,REPLEN ; Get length of replacement ADD T3,CHRNUM ; Add length of search string MOVEM T3,TXTMOV ; Save the size difference JUMPL T3,REPL.B ; Too long SKIPE T3 ; Any left over? CALL SHIFT ; Yes, remove excess characters SKIPG B,REPLEN ; Get length JRST RPL.Z1 ; Nothing to replace BPM T1,REPSTR ; Point to replacement string ILDB T2,T1 ; Get a byte IDPB T2,P1 ; Put it into the buffer SOJG B,.-2 ; Until done ;Now fix up the screen display RPL.Z1: MOVE T1,LINE ; Get current line SUB T1,TOPLIN ; Subtract screen top SKIPL DIRECT ; Were we searching backward? IFSKP. ; Yes... SKIPL T1 ; Are we still on the screen? JRST REPL.A ; No ELSE. ; No... CAIGE T1,^D24 ; Are we off the screen? JRST REPL.A ; No ENDIF. ; End of conditional MOVE T1,LINE ; Get line SUBI T1,^D12 ; Put it into the center SKIPGE T1 ; Are we still in the file? SETZ T1, ; No, set the top of screen MOVEM T1,TOPLIN ; Set new top of screen CALL CLRSCN ; Clear SKIPN SFIRST ; Don't update if just starting CALLRET .FFD ; No starting, redisplay and return CALLRET TYPLN1 ; Just display current line and ret ;Here to fix up part of the screen REPL.A: SKPOFF F.RPSH ; Repeating? JRST REP.A1 ; Yes, don't clear work space CALL CLRWRK ; Clear work space MOVE T1,LINE ; Get line number SUB T1,TOPLIN ; Find offset into screen SKIPE SFIRST ; Searching at first? CALLRET TYPLN1 ; Yes, type the line and ret CAIL T1,^D22 ; Was affected area just fixed? JRST CURPOS ; Yes, position and return REP.A1: CALL SETPTR ; Set the pointer CALL CURPOS ; Position cursor SKIPN TXTMOV ; Do we have to replace the remainder? JRST REP.A2 ; No, just the exact text CALL CLREOL ; Clear rest of line MOVE A,P1 ; Get pointer CALL TYPLIN ; Re-type the line CALL CURPOS ; Position cursor RET ; And return ; Here if the replacement string is longer that the search string REPL.B: CALL LINLEN ; How many chars are on this line? MOVN T1,TXTMOV ; Get the overrun length ADD T4,T1 ; Get destination column CAML T4,MAXCOL ; Would the line be too long? JRST RPL.B1 ; Yes, check it out MOVE D,P1 ; Save pointer CALL MAKSPC ; Insert (T1) spaces TYPERR BPM T1,REPSTR ; Point to the replacement string MOVE T2,REPLEN ; Get the length of the string MOVEM D,P1 ; Restore pointer RPL.B2: ILDB A,T1 ; Get a byte IDPB A,P1 ; And put it in the buffer SOJG T2,RPL.B2 ; And loop through all characters JRST RPL.Z1 ; Finish the replacement ;Here if the replacement string is too long RPL.B1: SKIPE PROG ; Program mode? JRST RPL.B3 ; Yes, error PUSH P,LINE ; Save current line CALL SETPTR ; Make sure pointer is set MOVE T3,CHRNUM ; Get length CALL SHIFT ; Delete that amount CALL LINACT ; Active line following? IFSKP. ; Yes CALL INLN2 ; Insert a following line MOVE A,P1 ; Copy pointer ILDB A,A ; Get following char CAIE A,SP ; Space? SKIPN A ; Or null? IFNSK. CALL SPLIT ; Split line at following word ELSE. CALL SPL.A ; Otherwise split in place ENDIF. ENDIF. CALL LINAC2 ; Line active before cursor? IFSKP. ; Yes CALL INLN2 ; Insert another AOS LINE ; Bump line ENDIF. MOVE T1,INDENT ; Get indent MOVEM T1,COL ; Set column CALL SETPTR ; Set the pointer MOVE A,P1 ; Point to destination BPM B,REPSTR ; Point to the string MOVN C,REPLEN ; It's this long MOVE T1,MAXCOL ; Get maximum column SUB T1,INDENT ; Find available length CAMLE C,T1 ; String short enough? MOVE C,T1 ; No, reset it SOUT% ; Move it MOVE T1,(P) ; Retrieve old value of line MOVEM T1,LINE ; And set it CALL SETPTR JRST EVE.A ; Finally, justify the paragraph ; Note line stays pushed! ;Here if the replacement is too long and we're in program mode RPL.B3: CALL CLRWRK ; Workspace again CALL SPCON ; Turn on special effects TYPNCR <% Replacement string is too long to fit> CALL SPCOFF ; Turn off effects SETZM REPLEN ; End of replacement string MOVEI A,HLDTIM ; Time to wait DISMS% ; Sleep CALL CLRWRK ; Clear the work space RET ; And return ;Here to just retype the changed part of the line REP.A2: HRROI A,REPSTR ; Get the string PSOUT% ; Type it CALL CURPOS ; Position RET ; And return Subttl Special functions -- Positioning ;These routines handle moving the cursor to special parts of the file. POSIT: CALL ICHAR ; Get a char FLGOFF F.NOPG ; None of these effect the page mark CAIN A,"L" ; Beginning of line? JRST POSBOL ; Yes CAIN A,"A" ; Append to line? JRST POSELN ; Yes CAIN A,"B" ; Beginning? JRST POSBEG ; Yes CAIN A,"E" ; End? JRST POSEND ; Yes CAIN A,"P" ; Last page? JRST POSPRV ; Yes CAIN A,"N" ; Next page? JRST POSNXT ; Yes CAIN A,"W" ; To next word? JRST POSWRD ; Yes CAIN A,"C" ; Centering formfeed? JRST CNTFFD ; Yes CAIN A,"T" ; Position to top? JRST POSTOP ; Yes RET ; None of the above ;Move cursor to beginning of file POSBEG: SETZM LINE ; Line zero SETZM COL SKIPN TOPLIN ; Already there? JRST POSCUR ; Yes, just position cursor SETZM TOPLIN ; No, reset JRST POSCOM ; Clear and re-display ;Move cursor to end of file POSEND: SETZM COL ; Column zero MOVE T1,HGHLIN ; Get highest line MOVEM T1,LINE ; Our new position SUB T1,TOPLIN ; Find out where we are CAIGE T1,^D24 ; On screen? JRST POSCUR ; Yes, just position the cursor MOVE T1,LINE ; Get position SUBI T1,^D12 ; Put us in middle of screen MOVEM T1,TOPLIN ; New top JRST POSCOM ; Finish up ;In-line cursor movement routines -- move to beginning and end of line ;Move cursor to beginning of line POSBOL: SKIPE T1,VALUE ; Any repeat count? JRST POSM.L ; Yes, multiple line positioning SETZM COL ; Zero the column SKIPE T1,INDENT ; Unless there's an indent MOVEM T1,COL ; In which case set it JRST CURPOS ; Set cursor and return ;Move cursor to end of line POSELN: CALL SETPTR ; Set pointer to current cursor posit CALL NXTWRD ; Get next word CAIA ; None, skip JRST POSE.B ; Found one, continue SETZM COL ; Start at beginning now CALL SETPTR ; Set the pointer CALL NXTWRD ; Anything there? JRST CURPOS ; No, position and return POSE.A: CALL SETPTR ; Set up the pointer CALL NXTWRD ; Get next word in line JRST POSE.C ; No more on line POSE.B: MOVEM T1,COL ; Set position of current word ADDM T2,COL ; Now position to next word AOS COL ; Bump to get past the word JRST POSE.A ; And try again POSE.C: SOS COL ; Back up one character JRST CURPOS ; And reset ;Move cursor to the beginning of the next word on the line. POSWRD: CALL NXTWRD ; Get next word coordinates JRST POSW.B ; None, go to next line CAMLE T1,COL ; Have we advanced? JRST POSW.A ; Yes, set the new column ADD T3,T1 ; No, so get to next word CAIL T3,^D79 ; Too far? JRST [ADD T1,T2 ; Yes, don't advance all the way JRST POSW.A] ; And jump to eol MOVEM T3,COL ; Set new column CALL SETPTR ; Set the pointer CALL NXTWRD ; Get next word JRST POSW.B ; None there ;Here to move to the next word POSW.A: MOVEM T1,COL ; Set new column CALL CURPOS ; Position RET ; And return ;Here to move to the next line POSW.B: FLGON F.FMOV ; Set forced move flag CALL .DWN ; Go down one line CALL DOIND ; Indent properly RET ; And return ;Move cursor a varying number of pages or lines ;Characters POSM.C: ADD T1,COL ; Get new column IDIVI T1,^D80 ; Find number of lines ADD T1,LINE ; Find new line number MOVEM T2,COL ; Set new column SKIPL T2 ; Is it non-negative? JRST POSM.Y ; Yes, join main stream ADDI T2,^D80 ; Correct the offset MOVEM T2,COL ; Set new column SOJA T1,POSM.Y ; And lower the line by one ;Pages POSM.P: IMULI T1,^D22 ; Then adjust number of lines MOVE T2,TOPLIN ; Get top line TRNA ; Skip ;Lines POSM.L: MOVE T2,LINE ; Get current line ADD T1,T2 ; Adjust current line ;All of the above POSM.Y: CAMLE T1,HGHLIN ; Too high? MOVEM T1,HGHLIN ; Yes, adjust SKIPGE T1 ; Too low? SETZ T1, ; Yes, adjust MOVEM T1,LINE ; Store the line value CAML T1,TOPLIN ; Below old top line? JRST PML.A ; Nope MOVEM T1,TOPLIN ; Set new top line CALL CLRSCN ; Clear the screen JRST .FFD ; And refresh ;Here if we're past old top line PML.A: MOVE T2,TOPLIN ; Get top of screen ADDI T2,^D23 ; Find maximum location CAMG T1,T2 ; On the screen? JRST CURPOS ; Yes, just position cursor MOVEM T1,TOPLIN ; Set new screen top CALL CLRSCN ; Clear the screen JRST .FFD ; And refresh ;Move cursor to previous page POSPRV: SKIPN T1,VALUE ; Numeric count? JRST .+3 ; No MOVNS T1 ; Negate the argument JRST POSM.P ; Yes, move pages SETZM COL ; Get to column zero SKIPN T1,TOPLIN ; At beginning? JRST PPRV.A ; Yes, no refresh SUBI T1,^D22 ; Back up a screen SKIPGE T1 ; Unless gone too far SETZ T1, ; Yes, set to zero MOVEM T1,TOPLIN ; Reset top line MOVE T1,LINE ; Recall the line SUBI T1,^D22 ; Up 22 lines SKIPGE T1 ; Still positive? SETZ T1, ; No, make us zero MOVEM T1,LINE ; Save new location JRST POSCOM ; Finish up ;Here if we merely need to move the current line without refreshing screen PPRV.A: SKIPN T1,LINE ; Get line RET ; Already homed - no changes SETZM LINE ; Get to line zero JRST POSCUR ; Position cursor and return ;Move cursor to next page POSNXT: SKIPE T1,VALUE ; Repeat count? JRST POSM.P ; Yes, move several pages SETZM COL ; Column zero MOVE T1,TOPLIN ; Get top of screen ADDI T1,^D22 ; Scroll it CAML T1,HGHLIN ; Compare to end of text JRST PNXT.A ; Too far MOVEM T1,TOPLIN ; Store new top line MOVE T1,LINE ; Recall the current line ADDI T1,^D22 ; Move to next page MOVEM T1,LINE ; And remember it JRST POSCOM ; Finish up ;Here if our destination is on the screen. Just get the cursor to end of text. PNXT.A: MOVE T1,HGHLIN ; Get highest line MOVEM T1,LINE ; Store it JRST POSCUR ; And position to there ;POSCOM routine - completion routine for all positioning. Refresh the screen ;and display new text. POSCOM: CALL CLRSCN ; Clear the screen FLGON F.INDT ; Indent after refresh JRST .FFD ; Display ;POSCUR routine - cursor is moving to a position on the screen, so no ;refresh is necessary. Just position the cursor after indenting. POSCUR: SKIPE T1,INDENT ; Any indent? MOVEM T1,COL ; Yes JRST CURPOS ; Position and return ;POSTOP routine -- position the current line at the top of the screen POSTOP: MOVE T1,LINE ; Get line SUB T1,TOPLIN ; Are we already there? JUMPLE T1,R ; Yes, nothing to do PUSH P,COL ; And col PUSH P,LINE ; Save current line SETZM COL ; Zero the column MOVEI A,^D23 ; Last line ADD A,TOPLIN ; Of screen MOVEM A,LINE ; Store it CALL CURPOS ; Position there MOVEI A,.PRIOU ; Output to tty HRROI B,[BYTE (7) 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12] MOVN C,T1 ; Number of lines SOUT% ; Go down MOVE T2,(P) ; Get current line setting EXCH T2,TOPLIN ; Set it and grab toplin ADDI T2,^D24 ; Add a screen EXCH T1,T2 ; T1 gets line, t2 gets count MOVEM T1,LINE ; Save new (temp) line CALL CURPOS ; Position to new location CALL FFD.A ; Refresh screen (partially) POP P,LINE ; And line POP P,COL ; Restore column JRST CURPOS ; And return to old place Subttl Text movement routines -- GETLIN ;Getlin accepts a parameter that indicates the number of lines to save. The ;saved text is inserted in a buffer and deleted from the screen and text. GETLIN: SKIPG VALUE ; Saved number? JRST GETL.A ; No CALL ICHAR ; Get following character MOVE T2,A ; Copy it MOVE A,VALUE ; Get count JRST GETL.B ; Continue on ;Read in the argument after the ^G command GETL.A: CALL GETNUM ; Get a number CAIA ; Skip JRST GETL.D ; Number returned, done MOVE T2,A ; Copy the terminating character MOVEI A,1 ; Assume one by default ;Check out the number returned GETL.B: CAILE A,^D100 ; Too many lines? TYPERR CAIN T2,"C" ; Copy? JRST GETL.D ; Yes CAIN T2,"M" ; Move? JRST GETL.C ; Yes TYPERR GETL.C: FLGON F.DGET ; Delete after copy GETL.D: MOVEM A,SAVNUM ; Save the number MOVE T1,LINE ; Get current line IMULI T1,20 ; Get words ADD T1,BUF ; Make an address HRLS T1 ; Put in left hand side HRRI T1,SAVBUF ; Destination IMULI A,20 ; Words to be saved BLT T1,SAVBUF-1(A) ; Transfer correct number CLRSKS F.DGET ; Are we deleting? RET ; No, just a copy MOVE T4,SAVNUM ; Yes, get number CALL DELLN1 ; Delete one line SOJG T4,.-1 ; Repeat for all lines CALL DISPLA ; Display changes RET ; And return Subttl Text movement routines -- RETLIN ;Retlin inserts the saved text into the buffer at the appropriate position. RETLIN: SKIPN SAVNUM ; Get number of saved lines RET ; None saved FLGOFF F.NEGR ; Clear negative retlin flag SKIPL SAVNUM ; Is it negative? IFSKP. ; Do the following if so FLGON F.NEGR ; Set the flag FLGOFF F.NBAK ; Assume backup is ok CALL LINAC2 ; Active line before cursor? IFSKP. ; Yes, do the following CALL LINACT ; Check if active line past col IFSKP. ; An active line, CALL INLN2 ; Insert a line after this one CALL SPLIT ; And split the current line ENDIF. AOS LINE ; Bump current line ELSE. FLGON F.NBAK ; Flag no backup after insertion ENDIF. ENDIF. MOVM T2,SAVNUM ; Get number of lines to insert MOVE T1,LINE ; And where to do it CALL ILINE ; Do the insert ;Here when the correct white space is there to overwrite. RTL.B: MOVE T1,LINE ; Get current line IMULI T1,20 ; Words ADD T1,BUF ; Make an address HRLI T1,SAVBUF ; Point to save buffer MOVEI T2,20 ; Words per line IMUL T2,SAVNUM ; Times number of lines SKPOFF F.NEGR ; Negative? MOVNS T2 ; Yes, negate answer ADDI T2,-1(T1) ; Make an address offset BLT T1,(T2) ; Transfer it SETZM COL ; Start at column zero SKPON F.NEGR ; Negative retlin flag? JRST RTL.C ; No, just display MOVE T1,LINE ; Get LINE value SKPOFF F.NBAK ; No backup flag? IFSKP. SOSGE T1,LINE ; Back up the line value SETZB T1,LINE ; Unless it went to -1 ENDIF. CAMGE T1,TOPLIN ; Backed up too far? JRST [MOVEM T1,TOPLIN ; Yes, correct it FLGON F.EMES ; Must correct the whole screen JRST .+1] ; Proceed PUSH P,LINE ; Save the line JRST EVE.A ; And justify ;Here for normal move RTL.C: FLGON F.INDT ; Indent after refresh CALL DISPLA ; Display the screen changes RET ; And return Subttl Text movement routines -- MOVPAR ;This routine will move a block of text bounded by special markers, not ; necessarily on line boundries. MOVPAR: FLGOFF F.COPY!F.MOVE!F.DELE ; Clear flags CALL ICHAR ; What follows? CAIN A,"C" ; Copy? FLGON F.COPY ; Yes CAIN A,"M" ; Move? FLGON F.MOVE ; Yes CAIN A,"D" ; Delete? FLGON F.DELE ; Yes CAIN A,"R" ; Return to first mark? JRST MVP.E ; Yes, go to a special routine SKPON F.COPY!F.MOVE!F.DELE ; Any set? TYPERR ;Check for double spacing and prohibit if set SKIPE DOUBLE ; Double spacing? TYPERR ;Here to move the text MVP.A: STKVAR ; Current cursor position MOVE T1,COL ; Get column MOVEM T1,ECOL ; Save it MOVE T1,LINE ; Store current line MOVEM T1,ELINE ; Store it IMULI T1,^D80 ; Multiply by chars per line ADD T1,ECOL ; Add column HRRZ T2,SLINE ; Starting line IMULI T2,^D80 ; Get character position ADD T2,SCOL ; Add starting column SUB T1,T2 ; Get number of chars AOJ T1, ; Bump by one to correct the count SKIPLE T1 ; Check it CAILE T1,17500 ; Check for too large TYPERR SKPON F.COPY ; Copying? JRST MVP.B ; No MOVE T2,SLINE ; Get line MOVEM T2,LINE ; Store it MOVE T2,SCOL ; And column MOVEM T2,COL ; Set that too CALL SETPTR ; Set pointer to it HRROI A,SPACES ; Initialize to spaces BPM B,SAVBUF ; Point to output buffer SETZ C, ; Until a null SIN% ; Make it neat MOVEI T2,^D80 ; Characters on a line SUB T2,COL ; Chars to transfer SUB T1,T2 ; Correct the count MOVE B,INDENT ; Get indent CAMLE B,COL ; Beyond current column? SETZ B, ; No, so start on the margin ADJBP B,[POINT 7,SAVBUF] ; Adjust pointer accordingly MOVE A,P1 ; Point to text MOVN C,T2 ; Get count SKIPE C ; Don't transfer nothing SIN% ; Transfer the characters BPM B,SAVBUF+20 ; Point to beginning of second line MOVN C,T1 ; Get remaining characters SKIPE C ; Check count SIN% ; Transfer complete string HRROI A,SPACES ; Spaces again SETZ C, ; Until a null SIN% ; Make it neat MOVE T2,ELINE ; Ending line SUB T2,SLINE ; Starting line AOJ T2, ; Bump it MOVNM T2,SAVNUM ; Save (-) as lines in buffer MOVE A,ELINE ; Get the line MOVEM A,LINE ; Restore it MOVE A,ECOL ; Get the column MOVEM A,COL ; And restore it SETOM SLINE ; Clear settings SETOM SCOL RET ; Return ;Here for a move or a delete MVP.B: CALL LINAC2 ; Line empty before cursor? IFSKP. ; No CALL LINACT ; Line empty after cursor? IFSKP. ; No CALL INLN2 ; Insert a new line CALL SPLIT ; And split the current one ENDIF. ELSE. SOS ELINE ; Back up the last line copied ENDIF. MOVE T2,SLINE ; Get starting line MOVEM T2,LINE ; Store it MOVE T2,SCOL ; And starting column MOVEM T2,COL ; Store it CALL SETPTR ; Set the pointer FLGOFF F.NBAK ; Assume backup CALL LINAC2 ; Line empty before cursor? IFSKP. ; No AOS SLINE ; So start at line+1 CALL LINACT ; Line empty after cursor? IFSKP. ; No CALL INLN2 ; Insert a new line CALL SPLIT ; And split the current one AOS ELINE ; Bump the end count ENDIF. ELSE. FLGON F.NBAK ; No backing up for justification ENDIF. MOVE T4,ELINE ; Get ending line SUB T4,SLINE ; Get difference JUMPL T4,MVP.D ; None to move MOVE T2,SLINE ; Get starting line MOVEM T2,LINE ; Set it SKPON F.MOVE ; Are we moving? JRST MVP.C ; No, deleting ;Copy the block of text to the save buffer IMULI T2,20 ; Multiply by words per line ADD T2,BUF ; Get starting location HRLS T2 ; Put into left side HRRI T2,SAVBUF ; Point to save buffer MOVEI T3,1(T4) ; Number of lines MOVNM T3,SAVNUM ; Save number of lines in buffer IMULI T3,20 ; Get number of words BLT T2,SAVBUF(T3) ; Copy several lines ;Here to delete the block of text MVP.C: CALL DELLN1 ; Delete a line SOJGE T4,.-1 ; Repeat until done ;Here to finish up and justify MVP.D: SETO T2, ; Flag to indicate no value EXCH T2,SLINE ; Store it SKPOFF F.NBAK ; Back up necessary? IFSKP. ; Yes SOSGE T2 ; Back up ac t2 SETZ T2, ; Unless we went too far ENDIF. MOVEM T2,LINE ; Set new line SETOM SCOL ; Clear starting column CAML T2,TOPLIN ; Still on the screen? IFSKP. ; If not on screen CALL CLRSCN ; Clear the screen MOVE A,LINE ; Restore old line value MOVE T1,A ; Get line position SUBI T1,^D12 ; Adjust it SKIPGE T1 ; Too small? SETZ T1, ; Yes, clear it MOVEM T1,TOPLIN ; Set new top line FLGON F.EMES ; Yes, make sure we refresh ENDIF. PUSH P,LINE ; Save current value JRST EVE.A ; Now go justify ;Here for the Return command. Restore the saved position and fix the display MVP.E: MOVE A,SCOL ; And the column SKIPGE A ; Valid value? TYPERR MOVEM A,COL MOVE A,SLINE ; Get the line MOVEM A,LINE CALL SETPTR ; Point us there MOVE A,LINE ; Get current line SUB A,TOPLIN ; Subtract the screen top JUMPL A,.+3 ; Negative? redo screen CAIGE A,^D24 ; Off the screen? JRST CURPOS ; No, position the cursor MOVE A,LINE ; Get line again SUBI A,^D12 ; Put it into the center SKIPGE A ; Is it non-negative? SETZ A, ; No, make it zero MOVEM A,TOPLIN ; Set new top of screen CALL CLRSCN ; And re-display CALL .FFD RET Subttl Justification routines ;Justify the text until we come to a line that is all spaces or we come to ;a line that doesn't change. EVEN: FLGOFF F.DBIN ; Assume no double input SKIPG A,VALUE ; Repeat count? SETO A, ; No, don't count MOVEM A,JCNT ; Set number of lines PUSH P,LINE ; Store line CALL ICHAR ; Get the next char CAIN A,"P" ; Paragraph? JRST EVE.A1 ; Yes CAIN A,"F" ; File? JRST EVE.B ; Yes CAIE A,"A" ; All double spaced? IFSKP. ; Yes FLGON F.DBIN ; Say double spaced input JRST EVE.B ; And even whole file ENDIF. CAIE A,"D" ; Are we doing double spaced input? IFSKP. ; Yes FLGON F.DBIN ; Say so JRST EVE.A1 ; And go even a paragraph ENDIF. POP P,LINE ; Wrong character RET ; None of the above ;Justify one paragraph -- easy! EVE.A: SKIPE DOUBLE ; Are we in double input mode? FLGON F.DBIN ; Yes, so try double output mode too SETOM JCNT ; Don't count lines EVE.A1: SETZM COL ; Start at beginning CALL SETPTR ; Make pointer right CALL JUSTIF ; Justify one paragraph JFCL ; We don't care if it's eof JRST EVE.C ; Done ;Justify the whole file EVE.B: SETZM COL CALL SETPTR ; Set the pointer EVE.B1: CALL JUSTIF ; Justify a paragraph JRST EVE.C ; Done MOVE T1,LINE ; Get next line CAMLE T1,HGHLIN ; Too high? JRST EVE.C ; Yes JRST EVE.B ; No, do next paragraph ;Here to display the current buffer with changes. EVE.C: POP P,LINE ; Restore original line SETZM COL ; Column zero CALL SETPTR ; Set the pointer FLGON F.INDT ; Indent after refresh TXZE F,F.EMES ; Error message on screen? JRST .FFD ; Yes, clear whole screen CALL CLREOS ; Clear to end of screen MOVE T1,LINE ; Get line MOVE T2,TOPLIN ; And top line ADDI T2,^D24 ; Add end of screen SUB T2,T1 ; True amount to refresh CALL FFD.A ; Refresh the screen below line RET ; Done ;Justify subroutine ;This routine justifies the text in the current paragraph. Special variables ;are: ; Fstlin - First line in paragraph ; JUSTIF: SKIPE PROG ; Programming mode? RET ; Yes, just return FLGOFF F.DBSP ; Not on permitted blank SETZB T4,COL ; Start at beginning of lines SETZM INPLIN ; Clear input and output counters SETZM OUTLIN JUST: CALL SETPTR ; Set the pointer CALL NXTWRD ; Get first word JRST [AOS A,LINE ; Bump the line CAMLE A,HGHLIN ; Compare for max RET ; End of file JRST JUST] ; Try again MOVE A,LINE ; Get current line MOVEM A,FSTLIN ; Store first active line MOVE P3,[POINT 7,SPARE] ; Point to buffer MOVEI B,SP ; Get a space MOVE C,T1 ; Copy position of first char in word SOJL C,JUS.B1 ; Pre-decrement count IDPB B,P3 ; Insert spaces to proper column AOJA T4,.-2 ; And loop, counting spaces ;Loop here getting one word after another JUS.B: CALL NXTWRD ; Get a word JRST ENDLIN ; End of line JUS.B1: MOVEM T1,COL ; New cursor posit CALL SETPTR ; Set p1 to it MOVE A,P3 ; Destination MOVE B,P1 ; Source ADD T4,T2 ; Add length of word CAMLE T4,MAXCOL ; Line now too long? JRST NEWLIN ; Yes MOVN C,T2 ; Length of word SOUT% ; Copy it MOVEM A,P3 ; Store new pointer LDB A,P3 ; Get last byte MOVEI D,SP ; Load a space CALL CHKTRM ; Check for sentance terminators JRST JUS.B2 ; None found IDPB D,P3 ; Found one, extra space needed AOJ T4, JUS.B2: IDPB D,P3 ; Load an extra space AOJ T4, ; Count word terminator ADDM T3,COL ; Point to next word CALL SETPTR ; Reflect the change JRST JUS.B ; And loop ;Endlin routine -- end of input line, so simply go on to the next. ENDLIN: AOS INPLIN ; Bump input line counter SKIPGE JCNT ; Skip counting if negative IFSKP. ; It isn't SOSG JCNT ; Count down number of lines JRST ENDPAR ; End of count, finish up ENDIF. TXC F,F.DBSP ; Toggle the doubling counter AOS T1,LINE ; Bump the line CAMLE T1,HGHLIN ; Too high? JRST ENDPAR ; Yes SETZM COL ; Start at beginning CALL SETPTR ; Set up the pointer MOVE T1,P1 ; Copy the pointer ILDB T2,T1 ; Get first char on line JUMPE T2,INPX ; Don't compare nulls MOVE T3,[POINT 7,[ASCIZ "!#*)]}>;=\./~"]] ; Point to special chars ILDB T1,T3 ; Get one CAMN T1,T2 ; Match? JRST ENDL.A ; Yes, new paragraph JUMPN T1,.-3 ; Loop if not null INPX: FLGOFF F.NELN ; Empty line CALL NXTWRD ; Get next word IFNSK. ; None there SKPON F.DBIN ; Double spaced input? JRST ENDL.B ; No, end of paragraph SKPON F.DBSP ; Double toggle cleared? JRST ENDL.B ; Yes, end of paragraph JRST ENDLIN ; No, advance to next line ENDIF. FLGON F.NELN ; A non-empty line CAME T1,INDENT ; Off the margin? CALL ENDL.C ; Yes, end of normal paragraph SKPON F.DBIN ; Double input mode? JRST JUS.B1 ; No, continue with processing SKPOFF F.DBSP ; Double toggle set? CALL ENDL.C ; Yes, should not be JRST JUS.B1 ; Continue on with processing ;ENDL.A - Handle a page marker carefully to avoid justifying it as text ENDL.A: CALL ENDPAR ; End of paragraph processing JFCL ; Expect skip return AOS LINE ; Start with line past page mark RETSKP ; Return from justif ;ENDL.B - Only dispatch to ENDPAR if the JCNT is negative. ENDL.B: SKIPGE JCNT ; Negative? JRST ENDPAR ; Yes, we're not counting lines JRST ENDLIN ; Yes, we are counting lines ;ENDL.C - Only dispatch to ENDPAR if JCNT negative, otherwise process. ENDL.C: SKIPL JCNT ; Negative? RET ; No, proceed POP P,A ; Yes, pop off return JRST ENDPAR ; And end the paragraph ;Newlin routine -- end of output line, so regroup NEWLIN: SUB T4,T2 ; Get original count back CALL MOVEIT ; Move the current line MOVE A,OUTLIN ; Number of lines in output buffer CAIGE A,100 ; Limit of 100 JRST JUS.B1 ; Within the limit JRST ENDPAR+1 ; Over, stop here ;Endpar - end of input text. We now adjust the space in the ;file by deleting or adding extra lines. ENDPAR: CALL MOVEIT ; Move current output line MOVE T2,OUTLIN ; Get output line count SKIPE DOUBLE ; Doubling? LSH T2,1 ; Yes, double the count MOVE T3,T2 ; Copy count ADD T3,FSTLIN ; Get starting line MOVEM T3,LINE ; Set it for ^vf command use SUB T2,INPLIN ; Get change input to output JUMPE T2,ENDP.B ; Equal, no change JUMPL T2,ENDP.A ; Lines to delete MOVE T1,FSTLIN ; Lines to add, get first line CALL ILINE ; Add (t2) lines at line (t1) JRST ENDP.B ; And do the transfer ;Here to delete lines ENDP.A: MOVNS T2 ; Negate to get lines to delete MOVE T3,T2 ; Copy that number ADD T3,FSTLIN ; T3 now has source for blt MOVE T1,FSTLIN ; T1 has destination IMULI T1,20 ; Word offset ADD T1,BUF ; Address IMULI T3,20 ; Same gyrations ADD T3,BUF HRL T1,T3 ; Make blt pointer MOVE T3,HGHLIN ; Get highest point SUB T3,T2 ; Adjust it MOVEM T3,HGHLIN ; And reset it IMULI T3,20 ; Calculate address ADD T3,BUF BLT T1,17(T3) ; Transfer the data MOVE T1,SPACES ; Load some spaces MOVEM T1,20(T3) ; Deposit them HRLI T1,20(T3) ; Source HRRI T1,21(T3) ; Destination IMULI T2,20 ; Get number of words to blank ADDI T2,20(T3) ; Last address to blank BLT T1,(T2) ; Finish up ;Now copy the lines from the output to the main buffer ENDP.B: MOVEI A,JBUF ; Output address MOVE B,FSTLIN ; First line of destination LSH B,4 ; Multiply by 20 ADD B,BUF ; Add in buffer HRLI A,444400 ; Make 36-bit byte pointers HRLI B,444400 ;Loop transferring a line at a time ENDP.C: MOVNI C,20 ; Transfer 20 words SIN% ; From source to dest SKIPN DOUBLE ; Double spacing? IFSKP. ; Yes PUSH P,A ; Save source BPM36 A,SPACES ; Load up pointer to spaces MOVNI C,20 ; Number of words SIN% POP P,A ; Restore pointer ENDIF. SOSLE OUTLIN ; Done right number of lines yet? JRST ENDP.C ; No, continue SKPOFF F.DBIN ; Double input? IFSKP. ; No, do SINGLE -> DOUBLE conversion SKIPN DOUBLE ; Double spacing? RETSKP ; No, done SKPON F.NELN ; Non-empty line following? CALL DELLN1 ; No, so delete following empty line ELSE. ; Here, do DOUBLE -> SINGLE conversion SKIPE DOUBLE ; Double output? RETSKP ; Yes, don't bother SKPON F.NELN ; Non-empty line follows? RETSKP ; No, it's empty, leave it alone MOVE T1,LINE ; Current line MOVEI T2,1 ; Only add one CALL ILINE ; Insert a line following paragraph ENDIF. RETSKP ; Now return ;Moveit subroutine - move the current output line into the input buffer. MOVEIT: SUBI T4,^D80 ; Get spaces left on line MOVEI B,SP ; Get a space IDPB B,P3 ; Deposit it AOJL T4,.-1 ; Loop until end of line AOS A,OUTLIN ; Bump output line pointer IMULI A,20 ; Word offset ADDI A,JBUF-20 ; Precise location MOVE B,A ; Copy it HRLI A,SPARE ; Source BLT A,17(B) ; Transfer the line MOVE T4,INDENT ; Reset line parameters MOVE P3,[POINT 7,SPARE] SKIPN A,INDENT ; Leading spaces RET ; Done, none MOVEI B,SP ; A space IDPB B,P3 ; Store one SOJG A,.-1 ; Loop RET ; Done ;CHKTRM subroutine - check for sentance terminators. Character to be checked ;is in A and skip return is taken if we find one. CHKTRM: CAIN A,"." ; Look for sentance terminators RETSKP ; Found one CAIN A,"!" ; Again RETSKP CAIN A,"?" ; And again RETSKP RET ; Didn't find one, return Subttl Pagination routines -- Routines to help auto-pagination ;Insert a page break at the begining of the current line. Set the HardPg ;flag so we know to look for the squiggle when showing soft breaks. PERMBK: SETZM COL ; Zero the column counter SOS LINE ; Move up a line CALL INLN2 ; Insert a blank line AOS LINE ; Move back down CALL SETPTR ; Set pointer to start of line MOVEI A,"~" ; Get a fake form feed IDPB A,P1 ; Deposit it SETOM HARDPG ; Say we have hard page breaks CALL SETPTR ; Set the pointer again CALL CLREOL ; Erase the line MOVE A,P1 ; Pointer to the line CALL DISPLA ; Display the changes RET ; And return ; Unpaginate the file (remove all hard page breaks): UNPAG: MOVE T1,HGHLIN ; Get highest line MOVEM T1,LINE ; Set it ;Loop through the file UNP.A: CALL CHKPAG ; Check for a page feed CALL DELLN1 ; Found, delete the line SOSLE LINE ; Drop line JRST UNP.A ; Loop through file SETZM LINE ; Finished, clean up SETZM COL SETZM TOPLIN CALL CLRSCN FLGON F.INDT ; Indent after refresh JRST .FFD ; Redisplay the screen ;Set up a header for the output pagination routine. SETHED: CALL WRKSPC ; Get header work space CALL SPCON ; Turn on effects HRROI A,ASC ; Load header string CALL GETSTR ; Get it into spare HRROI A,SPARE ; Point to string HRROI B,PGHEAD ; Destination MOVEI C,^D80 ; Number of bytes SETZ D, ; Terminator SIN% ; Do the transfer CAIGE C,^D79 ; Anything but the cr? IFSKP. ; Nope SETZM PGHEAD ; So clear the header JRST SETH.A ; And return ENDIF. SETO A, ; Set a to -1 ADJBP A,B ; Back up the byte pointer MOVE B,A ; And copy it HRROI A,SPACES ; Now load up on spaces SIN% ; Finish up SETH.A: CALL SPCOFF ; Special effects off CALL CLRWRK ; Clear the work space RET ; And return Subttl Show status command ;This command shows the current parameter settings on the bottom two lines ;of the screen. SHOW: CALL WRKSPC ; Clear workspace CALL SPCON ; Turn on the effects MOVEI A,SP ; Get a space SKIPG T1,INDENT ; Get starting point JRST .+3 ; At zero PBOUT% ; Type a space SOJG T1,.-1 ; Loop correct number of times MOVEI A,"[" ; Start screen PBOUT% MOVE T1,INDENT ; Get starting point ;Loop here doing spaces and tabs SHO.A: AOS T2,T1 ; Get copy of column CAML T2,MAXCOL ; Don't go too far JRST SHO.B ; We reached the end ADJBP T2,[POINT 1,TABS] ; Get pointer ILDB T3,T2 ; Get proper bit MOVEI A,"-" ; Prepare for a space SKIPE T3 ; Check MOVEI A,"T" ; Make it a tab instead PBOUT% ; Type it JRST SHO.A ; And loop ;We've reached the margin SHO.B: MOVEI A,"]" ; End the screen line PBOUT% ; Type it MOVEI A,SP ;GET A SPACE MOVEI T1,^D78 ;GET MARGIN FOR EFFECTS SUB T1,MAXCOL ;SUBTRACT MAXIMUM SOJLE T1,SHO.C ;NO MORE SPACES IF THERE ALREADY PBOUT% ;TYPE A SPACE JRST .-2 ;AND LOOP ;Now type out the parameters SHO.C: HRROI A,ASC< > PSOUT% MOVEI A,.PRIOU ;OUTPUT SETO B, ;CURRENT MOVX C,OT%NDA!OT%NSC ;FLAGS ODTIM% HRROI A,ASC< Ind:> ; String PSOUT% ; Type it MOVE B,INDENT ; Get value CALL TYPNUM ; Type it HRROI A,ASC< Max:> ; next PSOUT% MOVE B,MAXCOL ; Get value CALL TYPNUM ; Type it HRROI A,ASC< P-size:> ; next PSOUT% MOVE B,PAGSIZ ; Get it CALL TYPNUM HRROI A,ASC< A-save:> ; next PSOUT% MOVE B,NUMSCH ; Characters between saves CALL TYPNUM HRROI A,ASC< Pag:ON> ; Pagination SKIPN AUTOPG ; Test it HRROI A,ASC< Pag:OFF> ; Not set PSOUT% HRROI A,ASC< Dbl:ON> ; Double spacing SKIPN DOUBLE ; Test it HRROI A,ASC< Dbl:OFF> PSOUT% HRROI A,ASC< Lines:> ; next PSOUT% MOVE B,HGHLIN ; Number of lines CALL TYPNUM HRROI A,ASC< L:> ; Current line PSOUT% MOVE B,LINE CALL TYPNUM HRROI A,ASC< C:> ; Current column PSOUT% MOVE B,COL CALL TYPNUM CALL SPCOFF ; Turn off the special effects CALL ICHAR ; Wait for continuation CALL CLRWRK ; Clear the work space RET ; And return ;Typnum routine - type out number in B in decimal TYPNUM: MOVEI A,.PRIOU ; Output MOVEI C,12 ; Decimal NOUT% ; Type it ERCAL [MOVEI A,60 ; Get a zero PBOUT% ; Type it RET] ; And return RET ; Done Subttl Toggle zero output command ;Here we set a flag, telling us whether or not we are currently outputing ;to the terminal or to null, and set the primary output device accordingly ZOUT: CLRSKS F.ZOUT ; Were we outputing to null:? IFSKP. ; Yes... FLGOFF F.ZOUT ; Not any more MOVEI A,.FHSLF ; This process SETO B, ; Assume setting full display SPJFN% ; Set the primary jfn to tty: CALL HOMEUP CALL HOMEUP ; Home the cursor CALL CLS.A ; Clear the screen JRST .FFD.B ; Refresh the screen ENDIF. ; End of yes... ;Here if we are setting the output to null: FLGON F.ZOUT ; Set the flag MOVEI A,.FHSLF ; This process HRROI B,.NULIO ; Input from tty:, output nowhere SPJFN% ; Set it RET ; And return Subttl Special function control commands ;These functions are designed for a Viewpoint terminal, which have ;keys designed for ^B sequences. .FUN: CALL ICHAR ; Get an invisible character MOVEI T1,FUNMAX ; Get maximum function FUN.A: HRRZ T2,FUNTAB(T1) ; Get function code CAMN A,T2 ; Match? JRST FUN.B ; Yes SOJG T1,FUN.A ; Loop TYPERR FUN.B: SKIPE MOD2 ; Model two viewpoint? CAILE T1,6 ; And function 1-6? CAIA ; No to either, regular processing CALL ICHAR ; Yes, so eat cr after function key HLRZ T2,FUNTAB(T1) ; Get default destination IMULI T1,30 ; Thirty words per function SKIPN FUNCT(T1) ; Is function set up? JRST (T2) ; No, do the default MOVE T2,[POINT 7,FUNCT] ; Get pointer ADD T2,T1 ; Add offset FUN.B1: MOVEI A,.CTTRM ; This terminal ;Now do the user function via STI jsys FUN.C: ILDB B,T2 ; Get char JUMPE B,R ; Done, return CAIN B,"$" ; Dollar sign? MOVEI B,.CHESC ; Yes, make into an alt instead CAIE B,"^" ; An up-arrow? JRST FUN.D ; Nope, just send it ILDB B,T2 ; Get controlled char JUMPE B,R ; None CAIN B,"^" ; Another up-arrow? JRST FUN.D ; Yes, send it as regular text CAIL B,"a" ; Make it upper case CAILE B,"z" TRNA ; Skip SUBI B,SP ; Convert lower to upper SUBI B,100 ; Make it a control char SKIPGE B ; Test for negatives SETZ B, ; Make it a null instead ;Send the character FUN.D: STI% ; Put it in input buffer ERJMP FUN.E ; Intercept errors JRST FUN.C ; And get the next ;Here to intercept errors FUN.E: MOVEI A,.PRIIN ; Input CFIBF% ; Clear buffer HRROI A,ASC CALL ERMSA ; Always print the message RET ; Done ;Here for special functions which are variable ;Connected directory CONNEC: GJINF% ; Get job info HRROI A,SPARE ; Point to destination DIRST% ; Get the name SETZM SPARE ; Failed BPM T2,SPARE ; Point to spare buffer JRST FUN.B1 ; And process the string ;Daytime DAYTIM: HRROI A,SPARE ; Point to area used SETO B, ; Current daytime MOVX C,OT%NSC!OT%SCL ; No seconds ODTIM% ; Get the time BPM T2,SPARE ; Point to spare buffer JRST FUN.B1 ; And process the string ;User name USRNAM: GJINF% ; Get job info MOVE B,A ; Get user number HRROI A,SPARE ; Point to destination DIRST% ; Get the name SETZM SPARE ; Failed BPM T2,SPARE ; Point to spare buffer JRST FUN.B1 ; And process the string ;Function table FUNTAB: Z XWD TRATAB,"1" ; One XWD INSLIN,"2" ; Two XWD SEARCH,"3" ; Three XWD BAKTAB,"!" ; Four XWD DELLIN,"""" ; Five XWD POSWRD,"#" ; Six XWD R,"A" ; Function a XWD R,"B" ; Function b XWD CONNEC,"C" ; Function c XWD DAYTIM,"D" ; Function d XWD R,"E" ; Function e XWD R,"F" ; Function f XWD R,"G" ; Function g XWD R,"H" ; Function h XWD R,"I" ; Function i XWD R,"J" ; Function j XWD USRNAM,"U" ; Function U FUNMAX==.-FUNTAB-1 ; Number of entries Subttl Pattern matcher routines -- Maktab ;Maktab creates the pattern matching automaton. The algorithm is from ;Baase - Computer Algorithms pg. 180. Credit for this particular ;implementation goes to Steve Berlin. MAKTAB: MOVE T3,CHRNUM ; Get number of characters SETZM FLINK+1 ; Refer to algorithm for explanation MOVEI T1,2 MAKT.A: CAMLE T1,T3 ; Reached the end? RET ; Yes, done MOVE T2,FLINK-1(T1) MAKT.B: JUMPE T2,MAKT.C ; If equal MOVE T4,PAT(T2) CAMN T4,PAT-1(T1) JRST MAKT.C MOVE T2,FLINK(T2) JRST MAKT.B ; Loop MAKT.C: MOVEI T4,1(T2) MOVEM T4,FLINK(T1) AOJA T1,MAKT.A ; Loop Subttl Pattern matcher routines -- Getpat ;This routine reads in the pattern to be matched. We read it from the ;first line on the screen and repair it later. GETPAT: FLGOFF F.REPL ; Not in replacement mode yet CALL WRKSPC ; Get workspace set up CALL SPCON ; Turn on special effects SETZ T3, ; Character counter for maktab HRROI A,[ASCIZ .String:.] CALL GETSTR ; Read in input string CALL SPCOFF ; Special effects off BPM A,SPARE ; Point to beginning SKIPGE VALUE ; Are we searching backward? PUSH P,T3 ; Yes, push a zero to seperate us ;Now run through the string transferring the characters to PAT GTP.A: ILDB T1,A ; Get a character CAIN T1,ALT ; Is it an escape? JRST GTP.B ; Yes, replacement string coming CAIGE T1,"a" ; Check lower case JRST .+3 ; It isn't CAIG T1,"z" ; Within upper bound? SUBI T1,40 ; Yes, convert to upper case CAIN T1,"%" ; Wildcard character? SETO T1, ; Yes SKIPGE VALUE ; Are we searching backward? PUSH P,T1 ; Yes, save the string in the stack MOVEM T1,PAT+1(T3) ; Store character SKIPE T1 ; Skip if done AOJA T3,GTP.A ; And keep looping MOVEM T3,CHRNUM ; Store number of characters SKIPL VALUE ; Searching backward? RET ; No, return ;Here when reverse-searching: Read the characters off the stack, reversing ; the characters in the string we're searching for. GTP.A1: SETZ T3, ; Reset the pointer POP P,T1 ; Get the zero off the stack GTP.A2: POP P,T1 ; Get a char from the stack MOVEM T1,PAT+1(T3) ; Add the char to the search string SKIPE T1 ; Are we done? AOJA T3,GTP.A2 ; No, get the next one RET ; Return ;Here when a replacement string is forthcoming GTP.B: SKIPL VALUE ; Reverse searching? JRST GTP.B2 ; No, skip the next part SETZ T3, ; Reset the pointer GTP.B1: POP P,T1 ; Get a char from the stack MOVEM T1,PAT+1(T3) ; Add the char to the search string SKIPE T1 ; Are we done? AOJA T3,GTP.B1 ; No, get the next one GTP.B2: SETZ T1, ; Make it null MOVEM T1,PAT+1(T3) ; Terminate the array MOVEM T3,CHRNUM ; Store number of characters BPM B,REPSTR ; Point to replacement string dest MOVEI C,^D80 ; Max length SETZ D, ; End on a null SIN% ; Copy the string SUBI C,^D79 ; Find length of string MOVNM C,REPLEN ; Store it FLGON F.REPL ; Replacement active RET ; Done Subttl Pattern matcher routines -- Match ;Match finds a match for the pattern in PAT, by searching through the text ;until we reach the end. MATCH: SKIPG T3,CHRNUM ; Get number of chars RET ; None, return PUSH P,LINE ; Save line and col PUSH P,COL AOS COL ; Bump the current column CALL SETPTR ; Set up the pointer PUSH P,P1 ; Save the pointer MOVE T1,HGHLIN ; Get highest line AOJ T1, ; Plus one line MOVEM T1,LINE ; Set it CALL SETPTR ; Set up a pointer HRRZ D,P1 ; Save addr for later reference POP P,P1 ; Restore the pointer MOVEI T2,1 ; Set up initial conditions ;Loop looking for end of file MAT.A: HRRZ T1,P1 ; Get current pointer CAMLE T1,D ; At end of file? JRST MAT.D ; Yes, failed SKIPL DIRECT ; Are we searching backward? JRST .+3 ; No, skip this test CAMGE T1,BUF ; Are we at the top of file? JRST MAT.D ; Yes, failed SKIPL DIRECT ; Are we searching backward? IFSKP. ; Yes... SETO A, ; -1 Character ADJBP A,P1 ; Point to it MOVE P1,A ; Copy the byte pointer LDB T1,P1 ; And get the character ELSE. ; Here if we didn't skip ILDB T1,P1 ; Get a char ENDIF. ; End if conditionals CAIL T1,"a" ; Is it a lower case letter? CAILE T1,"z" SKIPA ; No SUBI T1,40 ; Yes, make it upper case MAT.B: JUMPE T2,MAT.C ; Got back to beginning of pattern? SKIPL A,PAT(T2) ; No, get next pattern char ; Skip if pattern is wild CAMN A,T1 ; Same as file character? JRST MAT.C ; Yes - check for end of pattern MOVE T2,FLINK(T2) ; No, follow failure link JRST MAT.B ; And loop ;Check for end of pattern MAT.C: CAMN T2,T3 ; At end of pattern? JRST MAT.E ; Yes, we win AOJA T2,MAT.A ; No, loop for more ;Here when we've failed MAT.D: POP P,COL ; Restore line and col POP P,LINE RET ; And return ;Here when we've found a match MAT.E: MOVN A,CHRNUM ; Get negative number of chars SKIPGE DIRECT ; Searching backward? SETO A, ; Yes, just move by one character ADJBP A,P1 ; Adjust pointer MOVE P1,A ; Save new pointer CALL SETLC ; Set line and column POP P,T1 ; Toss out the saved values POP P,T1 RETSKP ; And return Subttl Terminal control routines ;Homeup routine - get to the real home position, which is screwed up on ;ADDS terminals. HOMEUP: MOVE A,TJFN ; Get image tty jfn HLRO B,HOMTAB(P2) ; Address of homeup string HRLI B,441000 ; Set up 8-bit pointer HRRE C,HOMTAB(P2) ; Length of string (negative) SOUT% ; Type it and home up RET ; Done ;CLREOL routine - blank out the line from COL to EOL ;This is done by sending the appropriate character sequence to clear to ;end of line, and internally replacing text by spaces. CLREOL: CALL CURPOS ; Position the cursor CLL.A: MOVE A,TJFN ; Get image tty jfn HLRO B,CELTAB(P2) ; Get clear end of line sequence HRLI B,441000 ; Set up 8-bit pointer HRRE C,CELTAB(P2) ; Number of characters SOUT% ; Type it RET ; Done ;CLREOS routine - blank out the screen from current position down ;Done by sending a clear eos string and internally blanking out the text. CLREOS: CALL CURPOS ; Position cursor CLS.A: MOVE A,TJFN ; Get image tty jfn HLRO B,CESTAB(P2) ; Get address of string for clear eos HRLI B,441000 ; Set up 8-bit pointer HRRE C,CESTAB(P2) ; Get count SOUT% ; Type it and clear to eos RET ; Done ;CLRSCN -- Clear the screen. Just output a form feed if possible, otherwise ;home up and clear to end of screen. CLRSCN: SKPOFF F.NFFD ; No form feed? JRST CLRS.A ; That's right MOVEI A,14 ; Get a form feed PBOUT% ; Type it RET ; And return ;Here to do it the hard way CLRS.A: CALL HOMEUP ; Home CALL CLS.A ; And clear RET ; Done Subttl NXTWRD - Find the next word in the file ;Find starting and finishing position of next word, and length including ;trailing spaces. If we are in the middle of a word, we back up to the start. ;If not in a word, we advance to the next one. This algorithm will not advance ;lines, and takes the non-skip return if no word is found within bounds. NXTWRD: MOVE T1,COL ; Get current column MOVE B,P1 ; Get pointer ILDB A,B ; Get first char JUMPE A,NXT.B ; A neo-space? CAIN A,SP ; A space? JRST NXT.B ; Yes, go forward ;Look for the start of this word NXT.A: JUMPLE T1,NXT.B ; Don't back up too far MOVE A,B ; Character, go backward MOVNI B,2 ; Go back 2 for ildb loop ADJBP B,A ; Back it up ILDB A,B ; Get a char SOJ T1, ; Count down column JUMPE A,NXT.B ; Check for neo-space CAIE A,SP ; A space? JRST NXT.A ; No, keep searching ;Here at beginning of field, scan to first non-space NXT.B: JUMPE A,.+3 ; Check for neo-space CAIE A,SP ; A space? JRST NXT.C ; Not a space ILDB A,B ; Get next CAIGE T1,^D79 ; Too far? AOJA T1,NXT.B ; Not yet RET ; Yes, quit ;Here at the beginning of the field NXT.C: MOVE T2,T1 ; Get current column NXT.C1: CAIL T2,^D79 ; End of line? JRST NXT.D ; Yes ILDB A,B ; Get char JUMPE A,NXT.D ; Check for a neo-space CAIN A,SP ; Check for a space JRST NXT.D ; It is, field is done AOJA T2,NXT.C1 ; It isn't, keep looking ;We've found the end, now look for number of trailing spaces NXT.D: MOVEI T3,1(T2) ; Start at next position NXT.D1: CAIL T3,^D79 ; Are we at the end? JRST NXT.E ; Yes ILDB A,B ; Get a char JUMPE A,.+3 ; A neo-space? CAIE A,SP ; Space? JRST NXT.E ; No, done AOJA T3,NXT.D1 ; Yes, keep looking ;Here when we're done NXT.E: SUB T2,T1 ; Get counts SUB T3,T1 ; For both AOJ T2, ; Count starting char AOJA T3,RSKP ; Done, return Subttl Adjustment routines -- FILL ;The FILL routine takes input text terminated by a null and puts it into ;80-column lines buffered with spaces. The JFN of the input file ;is in AC A, and the address of the output buffer is in BUF. The data is ;copied until we exceed MAXLIN lines from the start or until EOF. FILL: SETZM PGHEAD ; Zero the page header FLGOFF F.IEOF ; No input end of file MOVEM A,P3 ; Store the jfn SETZM HARDPG ; No hard page breaks seen yet SKIPE T4,CIPHER ; Are we ciphering? JRST CIP.IN ; Yes, special handling SETZM HGHLIN ; Start at line zero SETOM LINE ; Line counter SETZM COL ; Zero the column STKVAR ; Get extra variable MOVEI T1,^D78 ; Get maximum margin SUB T1,MAXCOL ; Get difference MOVEM T1,MARDIF ; Save it SETZM BFRCNT ; No characters yet ;Check for autopagination in effect in file -- if so, set it BIN% ; Get first byte of file ERJMP FIL.D1 ; Can't, assume eof JUMPN B,[BKJFN% ; Not null, back up JFCL ; Ignore errors JRST FIL.A] ; And try again SKIPE AUTOPG+OFFSET## ; Get original command line switch val SETOM AUTOPG ; Not off, make sure set ;Loop here making each line into 80 width chunks. FIL.A: AOS T3,LINE ; Bump the line count CAMLE T3,MAXLIN ; Don't go too far JRST FIL.D ; Quit while ahead SETZM COL ; Clear the column CALL SETPTR ; Set up the byte pointer SETOM LSTSPC ; Last space seen SETZ T1, ; Clear column counter ;Obtain the actual character FIL.B: CALL NXTCHR ; Get next character JRST FIL.D1 ; No next, eof FIL.S: CAIN B,15 ; Ignore cr JRST FIL.B SKPON F.PMRK ; Page marks? JRST FIL.S1 ; No, keep looking CAIE B,12 ; Line feed? JRST FIL.B ; No, discard characters FLGOFF F.PMRK ; Turn off the flag SETZM COL ; Column zero SETOM LSTSPC ; No last space SKIPE HARDPG ; Hard page? AOS LINE ; Yes, add one CALL SETPTR ; Set the pointer MOVEI T1,3 ; Three line feeds FIL.S0: CALL NXTCHR ; Get next JRST FIL.D1 ; Eof CAIN B,12 ; Line feed? SOJG T1,FIL.S0 ; Yes, continue JUMPE T1,FIL.B ; Three lfs, get next character JRST FIL.S ; Not three, process this character FIL.S1: CAIE B,14 ; Form feed? JRST FIL.S8 ; No, next test SKIPE AUTOPG ; Autopagination in effect? IFSKP. ; No MOVEI B,"~" ; Get substitution char JRST FIL.B4 ; And deposit it ENDIF. CALL NXTCHR ; Get next character JRST FIL.D1 ; No next JUMPE B,FIL.S2 ; Null, soft page mark ;Proceed with hard page mark SETOM HARDPG ; Hard pages in file MOVEI A,"~" ; Page marker char IDPB A,P1 ; Store it CAIN B,15 ; Cr? JRST FIL.S4 ; Yes, obtain a header JRST FIL.S7 ; Proceed with eating characters ;Soft page mark FIL.S2: CALL NXTCHR ; Get next character JRST FIL.D1 ; No next CAIE B,15 ; Cr? JRST FIL.S7 ; No, soft page w/o header ;Read a header into PGHEAD -- we've found a CR marker FIL.S4: SKIPE PGHEAD ; Page header stored yet? JRST FIL.S7 ; Yes, don't repeat it MOVEI T2,^D70 ; Line limit BPM T1,PGHEAD ; Point to buffer CALL NXTCHR ; Read a character JRST FIL.S7 ; None there CAIN B,SP ; Space? SOJG T2,.-3 ; Yes, don't save leading ones JUMPLE T2,FIL.S7 ; If exhausted, don't save a header JRST FL.S5A ; Process this character FIL.S5: CALL NXTCHR ; Get next JRST FIL.S6 ; Finished FL.S5A: JUMPE B,FIL.S6 ; End on a null CAIGE B,SP ; Check for control chars JRST FL.S5B ; Found one, probably cr, discard line IDPB B,T1 ; Store it SOJG T2,FIL.S5 ; Loop until done FL.S5B: SETZM PGHEAD ; Ran out, don't save header JRST FIL.S7 ; Proceed with eating line ;Here when header probably finished FIL.S6: MOVEI B,SP ; Load a space IDPB B,T1 ; Store it SOJG T2,.-1 ; Fill up rest of line ;Regular soft page w/o header, discard it FIL.S7: FLGON F.PMRK ; Flag the mark JRST FIL.B ; Get and test next one ;Proceed with next test FIL.S8: CAIN B,12 ; Handle lf specially JRST FIL.A JUMPE B,FIL.B4 ; Treat nulls like spaces CAIE B,11 ; Tab? JRST FIL.B2 ; No, skip MOVEI B,SP ; Load a space instead ;Loop inserting multiple spaces in place of a tab FIL.B1: IDPB B,P1 ; Insert a space AOJ T1, ; Bump column counter CAMLE T1,MAXCOL ; Too high? JRST FIL.B5 ; Yes TRNN T1,7 ; Check tab position JRST FIL.B ; Yes, enough spaces JRST FIL.B1 ; No, keep looping ;Not a tab, continue checking FIL.B2: CAIGE B,SP ; Check for control characters JRST FIL.B ; And toss them out! CAIN B,177 ; Also check for delete JRST FIL.B ; And discard that too FIL.B4: IDPB B,P1 ; Deposit character SKIPE B ; Null? CAIN B,SP ; Or space? MOVEM T1,LSTSPC ; Yes, count last space AOJ T1, ; Bump column counter CAMG T1,MAXCOL ; Too far? JRST FIL.B ; Nope, keep going ;Here we handle a line which must be broken at the spot FIL.B5: SKIPN XPNCOL ; Are we expanding? JRST FL.B5B ; No AOS T3,MAXCOL ; Bump maximum column CAILE T3,^D78 ; Too far? JRST FL.B5A ; Yes MOVEM T3,XPNCOL ; Keep track of it JRST FIL.B ; Keep going ;Here when we really must break FL.B5A: SOS MAXCOL ; Bump down count again FL.B5B: JUMPE B,FIL.B8 ; Break on nulls CAIN B,SP ; And spaces JRST FIL.B8 SETZ B, ; Make b into a null SKIPGE T3,LSTSPC ; Get last space position JRST FIL.B7 ; None, break here SUB T1,T3 ; Get amount to back up CAMLE T1,BACKUP ; Too far? JRST FIL.B7 ; Yes MOVNI T4,-1(T1) ; Copy length, make negative ADJBP T4,P1 ; Get copy of byte pointer AOS LINE ; Bump line count SKIPE T3,INDENT ; Get indention MOVEM T3,COL ; Set it CALL SETPTR ; Set up the pointer MOVE T3,INDENT ; Remove indent from line length ADDI T3,2 ; Allow for transferred characters SETOM LSTSPC ; Clear last space counter ;Loop here transfering characters down a line until done FIL.B6: SOJLE T1,FIL.B ; Where to go when done ILDB T2,T4 ; Get a byte DPB B,T4 ; Overwrite it with a space IDPB T2,P1 ; Copy to new place JRST FIL.B6 ;Here when we have to break the line in place FIL.B7: MOVNI T3,2 ; Back two bytes ADJBP T3,P1 ; Adjust byte pointer AOS LINE ; Bump the line SKIPE T1,INDENT ; Get indention MOVEM T1,COL ; Set it CALL SETPTR ; And set a new pointer ILDB T1,T3 ; Get byte MOVEI T2,"-" ; Get a hyphen DPB T2,T3 ; Overwrite the character ILDB T2,T3 ; Get the next byte DPB B,T3 ; Overwrite with null IDPB T1,P1 ; Deposit on next line IDPB T2,P1 MOVE T1,INDENT ; Set starting column for next line SETOM LSTSPC ; Clear last space counter JRST FIL.B ; Proceed ;Here when we are breaking the line right on a space. Just remember to ; start the next line on the indentation. FIL.B8: AOS LINE ; Bump the line SKIPE T1,INDENT ; Get indention MOVEM T1,COL ; Set it CALL SETPTR ; Set the pointer SETOM LSTSPC ; Clear last space counter MOVE T1,INDENT ; Set new count JRST FIL.B ; Proceed ;Here we fill out the very last line. FIL.D: SOS LINE ; Decrement line (to be Maxlin) FIL.D1: MOVE T3,LINE ; Get line count MOVEM T3,HGHLIN ; Store highest line RETSKP ; Done ;Routine to input next character. Skip return if character in B, ; otherwise non-skip on EOF ;Use SIN% to obtain chunks of the file, then use ILDB on each character. NXTCHR: SOSL BFRCNT ; Characters remaining? JRST NXC.C ; Yes, go get one SKPOFF F.IEOF ; End of file? RET ; Yes, done MOVE A,P3 ; Get the jfn BPM B,SPARE ; Point to buffer MOVNI C,3000 ; 3000 characters per sin SIN% ; Get them ERJMP NXC.A ; Can't MOVEI C,3000 ; Characters read MOVEM C,BFRCNT ; How many we've got to read JRST NXC.B ; Go get one ;Check out an error return from SIN. Probably EOF. NXC.A: MOVE A,P3 ; Get jfn GTSTS% ; Get status TXNN B,GS%EOF ; Skip if eof JRST NXC.ER ; No, error ADDI C,3000 ; Find how many actually read JUMPE C,R ; None, end of file FLGON F.IEOF ; Say end of file next time MOVEM C,BFRCNT ; Store count ;Here to set up new byte pointer NXC.B: SOS BFRCNT ; Reading one BPM A,SPARE ; Point to buffer MOVEM A,CHRPTR ; Store in pointer ;Here to obtain the character NXC.C: ILDB B,CHRPTR ;GET CHARACTER RETSKP ;AND RETURN SUCCESS ;Here on errors NXC.ER: TYPE <? Error reading input file, file truncated at error> MOVEI A,^D3000 ; 3 seconds DISMS% RET ;DONE Subttl Adjustment routines -- EMPTY ;This routine is the opposite of FILL, as might be expected -- it takes the ;buffer which starts at location BUF and transfers it to the block starting ;at location (A), stripping off the trailing spaces as it goes. It does ;HGHLIN lines before terminating. ;UNFILL is an alternate entry used from the WPSIM main routine, which ;specifies that form feed conversion should take place. UNFILL: SKIPE T4,CIPHER ; Are we ciphering? JRST CIP.OU ; Yes, special handling MOVE T4,LETHED ; Set line counter to letterhead if any SKIPE AUTOPG ; Are we autopaging? SUBI T4,4 ; Yes, compensate for missing header SETZM HARDPG ; Assume soft page for now FLGON F.FFCV!F.TABC ; Form feed conversion SKIPN T1,STRPAG ; Any starting page number specified? MOVEI T1,1 ; No, start with page one MOVEM T1,PAGNUM ; Initialize the numbering EMPTY: MOVE C,BUF ; Source MOVE D,A ; Destination HRLI C,(POINT 7,0) ; Make into pointers HRLI D,(POINT 7,0) PUSH P,HGHLIN ; Store highest line SETZ T1, ; Get a null SKPON F.FFCV ; Form feed conversion? IFSKP. ; Yes SKIPE AUTOPG ; Autopaging? IDPB T1,D ; Yes, start with a null ENDIF. ;Loop here doing one line at a time EMP.A: MOVEI T1,^D80 ; Maximum allowed column SETZ B, ; Space counter ;Loop here for each character on the line EMP.B: ILDB T2,C ; Get a character SKIPN T2 ; Check for a neo-space MOVEI T2,SP ; Make it a real one SKPOFF F.TABC ; Tab conversion in progress? SKIPN FILTAB ; Converting spaces to tabs? JRST EMP.B1 ; No JUMPLE B,EMP.B1 ; Any stored spaces? TRNE T1,7 ; Are we at a tab stop? JRST EMP.B1 ; No MOVEI T3,11 ; Load a tab CAIN B,1 ; Only one space? MOVEI T3,SP ; Yes, don't use a tab IDPB T3,D ; Store it SETZ B, ; Clear stored space count ;Here to check for form feed conversion EMP.B1: SKPON F.FFCV ; Form feed conversion? JRST EMP.B2 ; No CAIE T2,"~" ; Page break? JRST EMP.B2 ; No, continue SKIPE AUTOPG ; Autopagination? IFSKP. ; No MOVEI T2,14 ; Load form feed JRST EMP.B2 ; And process it as regular char ENDIF. SETOM HARDPG ; A hard page break JRST EMP.F ; Yes, handle form feeds EMP.B2: SOJLE T1,EMP.E ; End of line CAIN T2,SP ; Space? AOJA B,EMP.B ; Yes, count it MOVEI T3,SP ; Get a space ;Here when we've got a non-space character EMP.C: SOJL B,EMP.C1 ; Count down stored spaces IDPB T3,D ; Deposit them JRST EMP.C ; Do as many as necessary ;Here when we've processed all stored spaces EMP.C1: SKIPN CTRLCV ; Convert control chars? JRST EMP.D ; Nope SKPON F.FFCV ; Is this the real output? JRST EMP.D ; No, don't output escapes to tty! CLRSKS F.UPAR ; Up-arrow last character? IFSKP. ; Yes CAIL T2,"a" ; Check lower case SUBI T2,40 ; Yes, convert to upper SUBI T2,100 ; Make it a control char SKIPGE T2 ; Allowed value? SETZ T2, ; No, make it a null JRST EMP.D ; Go process it ENDIF. CAIE T2,"$" ; A dollar sign? JRST EMP.C2 ; No, try an "^" MOVEI T2,ALT ; Get an escape JRST EMP.D ; Deposit and get next character EMP.C2: CAIE T2,"^" ; An uparrow? JRST EMP.D ; No, keep checking FLGON F.UPAR ; Yes, flag it JRST EMP.B ; And get next char ;Finally, process the character EMP.D: IDPB T2,D ; Deposit SETZ B, ; No more stored spaces JRST EMP.B ; Keep going ;Here at EOL - toss in a CRLF EMP.E: CAIE T2,SP ; Don't deposit a lone space IDPB T2,D ; Store the character EMP.E1: LDB T2,D ; Get the character CAIE T2,11 ; A tab? CAIN T2,SP ; Or a space? IFNSK. ; Yes SETO T2, ; Set to -1 ADJBP T2,D ; Back up the pointer MOVEM T2,D ; Reset the pointer JRST EMP.E1 ; And try next ENDIF. MOVEI T2,15 ; Get a cr IDPB T2,D ; Deposit it MOVEI T2,12 ; Get a lf IDPB T2,D ; Deposit it SOSGE HGHLIN ; Count down number of lines JRST EMP.EX ; Done, finish up SKPON F.FFCV ; Are we converting form feeds? JRST EMP.A ; No, do next line AOS T4 ; Up the line count SKIPE AUTOPG ; Are we autopaginating? CAMGE T4,PAGSIZ ; Ready for a new page? JRST EMP.A ; No, do next line AOS HGHLIN ; Correct count, since emp.f changes it MOVE B,C ; Copy byte pointer ILDB A,B ; Get first byte of next line CAIN A,"~" ; Page? JRST EMP.A ; Yes, don't make two of them JRST EMP.F ; No, put in a page break ;Finish up and restore flags EMP.EX: POP P,HGHLIN ; Restore pushed data FLGOFF F.FFCV ; No more form feed conversion SETZ T2, ; Get a null IDPB T2,D ; And tack it on. ;Now trim off the trailing blank lines EMP.E2: MOVNI T1,3 ; Three positions ADJBP T1,D ; Back up the pointer LDB T3,T1 ; Get a byte CAIE T3,12 ; A line feed? RET ; Done IDPB T2,T1 ; Yes, null out succeding crlf MOVEM T1,D ; Set up pointer JRST EMP.E2 ; And try again ;Handle page header conversion here EMP.F: SETZ T4, ; Back at line 0 ;Eat the rest of the input line EMP.F0: SOJLE T1,EMP.F1 ; End of line ILDB T2,C ; Get a character JRST EMP.F0 ; Loop EMP.F1: PUSH P,C ; Save c MOVEI C,12 ; Prepare for number output in decimal MOVEI A,14 ; Get a form feed IDPB A,D ; Toss it in SETZ A, ; A null SKIPN HARDPG ; Are we writing a hard page break? IDPB A,D ; No, so follow the ^L with a null HRROI A,PGHEAD ; Page header string SKIPN PGHEAD ; Only if set up JRST EMP.F4 ; Otherwise another type used MOVEI T2,15 ; Carriage return IDPB T2,D ; Deposit to say header coming SKIPG T1,INDENT ; Indention used? JRST EMP.F2 ; No, regular MOVEI T2,SP ; Get a space IDPB T2,D ; Deposit it SOJG T1,.-1 ; Loop until done EMP.F2: MOVE T1,MAXCOL ; Get right margin SUB T1,INDENT ; Sub left SUBI T1,10 ; Sub page count BPM T2,PGHEAD ; Point to page header ILDB T3,T2 ; Get a byte IDPB T3,D ; Deposit it SOJG T1,.-2 ; Loop until done SETZ T2, ; Null IDPB T2,D ; Tack onto end of header MOVEI T1,5 ; Get length of page string BPL T2, ; Source ILDB T3,T2 ; Get a byte IDPB T3,D ; Deposit it SOJG T1,.-2 ; Loop until done AOS B,PAGNUM ; Get page MOVE A,D ; Get pointer NOUT% ; Type number JFCL MOVE D,A ; Restore pointer JRST EMP.F5 ; Finish up and return ;Here for an alternate paging style EMP.F4: MOVE T1,MAXCOL ; Get right margin SUB T1,INDENT ; Subtract left LSH T1,-1 ; Divide by two ADD T1,INDENT ; And add indentation SUBI T1,3 ; Minus three for dashes MOVEI T2,SP ; Get a space IDPB T2,D ; Deposit it SOJG T1,.-1 ; Deposit that many spaces MOVEI T3,"-" ; Get a dash IDPB T3,D IDPB T2,D ; Another space AOS B,PAGNUM ; Get page number MOVE A,D ; Copy pointer NOUT% ; Type the number JFCL MOVE D,A ; Restore pointer IDPB T2,D ; Now the space IDPB T3,D ; And the dash ;Here to finish up EMP.F5: BPM T2,[BYTE(7)15,12,12,12,12] MOVEI T1,5 ; End the line ILDB T3,T2 ; Get a byte IDPB T3,D ; Deposit it SOJG T1,.-2 ; And loop POP P,C ; Restore the pointer SOSLE HGHLIN ; Count down lines JRST EMP.A ; And do the next JRST EMP.EX ; If done, finish up ;Ciphering support routines for input and output ;Random number routine - Copied from FORLIB version 6 RANDOM: MOVE T1,T4 ; Get seed MUL T1,[4544,,503720] ; Multiply DIV T1,[17777,,-1] ; Divide MOVEM T2,T4 ; Save new seed RET ; Done ;Input ciphering routine CIP.IN: MOVE T3,BUF ; Get starting address CIP.I1: BIN% ; Get a byte ERJMP CIP.I2 ; Probably eof CALL RANDOM ; Get a random number XOR B,T4 ; Xor our byte MOVEM B,(T3) ; Store it AOJA T3,CIP.I1 ; And loop for more ;Here on probable eof CIP.I2: GTSTS% ; Get status TXNE B,GS%EOF ; Eof? JRST CIP.I3 ; Yes TYPE <? Error reading input file, file truncated> MOVEI A,HLDTIM ; 1.5 seconds DISMS% ; Leave message on CIP.I3: SUB T3,BUF ; Get number of words IDIVI T3,20 ; Get number of lines MOVEM T3,HGHLIN ; Save the value SETZM CIPHER ; Don't cipher the output RETSKP ; Done ;Output ciphering routine CIP.OU: MOVN B,HGHLIN ; Get highest line SOJ B, ; Bump it to set up a count IMULI B,20 ; Get number of words HRL A,B ; Set up an aobjn MOVE B,BUF ; Get starting address CIP.O1: MOVE C,(B) ; Get the byte CALL RANDOM ; Get a random seed XOR C,T4 ; Xor it MOVEM C,(A) ; Store the byte AOJ B, ; Bump the pointer AOBJN A,CIP.O1 ; Loop until done RET ; Done Subttl General subroutines ;MOVLIN routines - transfer a line from one place in the buffer to ;another. Assumes T1 contains the source line number and the entry ;point indicates whether we're moving up or down. ;Enter here if T2 contains number of words to move MOVLIN: MOVE A,T1 ; Get source IMULI A,20 ; Get word address ADD A,BUF ; Make buffer address HRLS A ; Put into left hand side ADDB A,T2 ; Make right side point to proper line BLT A,17(T2) ; Make the transfer RET ; Done ;Linlen routine -- set T4 to position of last character on line LINLEN: PUSH P,COL ; Save current column MOVEI T4,^D80 ; Get last position MOVEM T4,COL ; Store it CALL SETPTR ; Set the pointer LIN.A: LDB B,P1 ; Get a byte JUMPE B,LIN.B ; A null CAIE B,SP ; Space? JRST LIN.C ; Not a space LIN.B: SETO A, ; Minus one ADJBP A,P1 ; Back up the pointer MOVEM A,P1 ; Restore it SOJG T4,LIN.A ; Keep looking MOVEI T4,1 ; Prepare for subsequent lowering ;Here when we've found a non-space character LIN.C: POP P,COL ; Restore old column CALL SETPTR ; Restore pointer SOJA T4,R ; And return ;WRKSPC and CLRWRK -- Obtain/restore workspace at bottom of screen ;Clear bottom two lines of screen for special purpose use WRKSPC: PUSH P,LINE ; Save line and col PUSH P,COL MOVE T1,TOPLIN ; Get top line ADDI T1,^D22 ; Add most of screen MOVEM T1,LINE ; Set it SETZM COL CALL CLREOS ; Clear the text area POP P,COL ; Restore line and col POP P,LINE RET ; And return ;Restore the bottom two lines to their normal state CLRWRK: PUSH P,LINE ; Store current line PUSH P,COL ; And column MOVE T1,TOPLIN ; Get top of screen ADDI T1,^D22 ; Get to last line minus one MOVEM T1,LINE ; Set new line SETZM COL ; And column CALL CLREOS ; Clear to end of screen MOVE T1,LINE ; Get line number back MOVEI T2,2 ; Two lines to refresh SKIPN SFIRST ; Search mode? CALL FFD.A ; No, redisplay the lines POP P,COL ; Get column and line back POP P,LINE CALL CURPOS ; Position RET ; And return ;FNDBRK - Find blank line nearest current position ;We go down and up three lines from current position searching for a line ;containing all blanks. If found we delete it, if not we return with LINE ;at its original setting. FNDBRK: MOVE T1,INDENT ; Get indentation MOVE T2,LINE ; Get line CALL CHKBRK ; Check for a break RET ; Found AOJ T2, ; Bump line CALL CHKBRK ; Try again RET SUBI T2,2 ; Try line-1 CALL CHKBRK ; Try again RET SOJ T2, ; Try line-2 CALL CHKBRK RET ADDI T2,4 ; Try line+2 CALL CHKBRK RET SUBI T2,2 ; Last chance failed MOVEM T2,LINE ; Reset RET ; And return ;Chkbrk routine - check for a broken line, return with skip if not found CHKBRK: MOVEM T1,COL ; Set indentation MOVEM T2,LINE ; Set the line CALL SETPTR ; Set the pointer ILDB A,P1 ; Get a byte JUMPE A,R ; Return if null CAIN A,SP ; Or space RET RETSKP ; Anything else gets a skip ;CHKPAG routine - check for a page marker at the beginning of the line CHKPAG: SETZM COL ; Clear column CALL SETPTR ; Set the pointer ILDB B,P1 ; Get the character at start of line CAIN B,"~" ; Page mark? RET ; Yes, say so RETSKP ; No ;CURPOS - Cursor positioning routine. CURPOS: MOVE A,TJFN ; Get image tty jfn HLRO B,ADRTAB(P2) ; Addressing sequence HRLI B,441000 ; Set up 8-bit pointer HRRE C,ADRTAB(P2) ; Get number of chars SOUT% ; Type the beginning MOVE B,COL ; Check column CAIL B,^D80 ; Too high? SUBI B,^D80 ; Yes, make it modulo 80 MOVEM B,COL ; And store it back SKPOFF F.ANSI ; Check for ansi terminals JRST CURP.A ; They're a different ballgame MOVE B,LINE ; Get line number SUB B,TOPLIN ; Make into screen offset MOVE A,B ; Get line SKPOFF F.CXBY ; Check for reverse sequence terminals MOVE A,COL ; Get column instead ADDI A,SP ; Standard offset PBOUT% ; Send it MOVE A,COL ; Get column SKPOFF F.CXBY ; Check for x before y MOVE A,B ; Yes, get line instead ADDI A,SP ; Offset PBOUT% ; Type it RET ; Done ;Handle ANSI mode terminals -- the sequence is $[line; colh and the line ;and column have to be done carefully. CURP.A: SKIPN B,LINE ; Get the line JRST CURP.B ; It's zero SUB B,TOPLIN ; Subtract the offset AOJ B, ; Add in the offset MOVEI C,12 ; In decimal NOUT% ; Type it JFCL ; Ignore errors CURP.B: SKIPN D,COL ; Is column non-zero? JRST CURP.C ; No MOVEI B,";" ; Separator BOUT% ; Type it MOVEI B,1(D) ; Get column with offset MOVEI C,12 ; Decimal NOUT% ; Type it JFCL CURP.C: MOVEI B,"H" ; Terminates ascii positioning BOUT% RET ; Done ;ICHAR subroutine - get an invisible character by turning off the terminal ;echo before doing an input. Raise lower case input to upper. ICHAR: MOVEI A,.CTTRM ; Controlling terminal RFMOD% ; Read mode TXZ B,TT%ECO ; Turn off echo SFMOD% ; For following character PBIN% ; Read it in CAIN A,15 ; Is it a CR? PBIN% ; Yes, get the LF too CAIL A,"a" ; Find out if it's lower case CAILE A,"z" ; .. TRNA ; No, always skip SUBI A,SP ; Yes, convert to upper PUSH P,A ; Save the character MOVEI A,.CTTRM ; Get terminal designator back TXO B,TT%ECO ; Echo back SFMOD% ; And reset POP P,A ; Restore character RET ; Done ;ICHAR subroutine - get an invisible character by turning off the terminal ;echo before doing an input. ICHAR1: MOVEI A,.CTTRM ; Controlling terminal RFMOD% ; Read mode TXZ B,TT%ECO ; Turn off echo SFMOD% ; For following character PBIN% ; Read it in CAIN A,15 ; Is it a CR? PBIN% ; Yes, get the LF too PUSH P,A ; Save the character MOVEI A,.CTTRM ; Get terminal designator back TXO B,TT%ECO ; Echo back SFMOD% ; And reset POP P,A ; Restore character RET ; Done ;Routine to confirm an input request. This is requested by typing a bell ;and requiring one back. CONFRM: MOVE A,TJFN ; Get jfn MOVEI B,.CHBEL ; A bell BOUT% ; Send it CALL ICHAR ; Get a bell back CAIE A,.CHBEL ; Valid? RET ; Nope RETSKP ; Yes ;Indentation routines for input processing. ; DOIND - Indentation alone DOIND: MOVE C,INDENT ; Get indention MOVEM C,COL ; Store it CALL SETPTR ; Set pointer CALL CURPOS ; And cursor RET ; And return ;Routine to type out the current line starting at COL. We assume that the ;line is clear and thus avoid typing trailing spaces. The pointer is in A. ; TYPLN1 type the current line from the beginning: TYPLN1: PUSH P,COL ; Save the real column SETZM COL ; Set to the beginning of line CALL SETPTR ; Point there in the text CALL CURPOS ; Point to where it would be MOVE A,P1 ; Copy the current pointer CALL TYPLIN ; And do TYPLIN POP P,COL ; Reset the column count CALL SETPTR ; Reset the pointer CALLRET CURPOS ; Show where it is and return TYPLIN: MOVE T1,A ; Store pointer MOVEI C,^D80 ; Get line SUB C,COL ; Find characters left TYP.A: SETZ D, ; Space counter TYP.B: SOJLE C,TYP.C ; End of line ILDB B,A ; Get a character JUMPN B,TYP.B1 ; Look for nulls MOVEI B,40 ; Make it a space instead DPB B,A ; And overwrite the null TYP.B1: CAIN B,SP ; A space? AOJA D,TYP.B ; Yes, count it JRST TYP.A ; No, clear space count ;Here when the line is finished TYP.C: MOVNI C,^D80 ; Find count ADD C,COL ; Starting column ADD C,D ; Add trailing spaces MOVEI A,.PRIOU ; Output MOVE B,T1 ; Saved pointer JUMPE C,R ; Don't sout if nothing there SOUT% ; Type RET ; And return ;Routine to refresh the display, by rewriting any lines starting at ;LINE and going down. DISPLA: SETZM COL ; Now at column zero CALL CLREOS ; Clear to end of screen MOVE T1,LINE ; Where to start the refresh MOVE T2,TOPLIN ; Top of screen ADDI T2,^D24 ; Add end of screen SUB T2,LINE ; True amount to refresh FLGON F.INDT ; Indent after refresh CALL FFD.A ; Refresh rest of screen RET ; Done ;Routine to check for characters on the current line. Skips if the line ; has characters, non-skip if line is empty. LINACT: CALL SETPTR ; Reset pointer MOVE C,P1 ; Copy the pointer MOVEI A,^D80 ; Load up a column counter SUB A,COL ; Offset by current column ;Look for characters on this line LINA.A: ILDB B,C ; Get a char CAIE B,SP ; Space? SKIPN B ; Or neo-space? CAIA ; One or the other RETSKP ; Not a blank line SOJG A,LINA.A ; Count down RET ; No chars found, non-skip return ;Routine to check for characters before the cursor on the current line. ; Skip return if said characters exist. LINAC2: PUSH P,P1 ; Save pointer SETZ A, ; Clear an ac EXCH A,COL ; Get and clear column CALL SETPTR ; Set the pointer EXCH A,COL ; Reset column ;Look for characters before the cursor LIN2.A: CAML A,COL ; At the cursor? JRST LIN2.C ; Yes, done ILDB B,P1 ; Get a char CAIE B,SP ; Space? SKIPN B ; Neo-space? CAIA ; Yes JRST LIN2.B ; No, characters on line AOJA A,LIN2.A ; Keep looking ;Here when characters found, bump the return pc LIN2.B: AOS -1(P) ; Remember pushed value LIN2.C: POP P,P1 ; Restore it RET ; And return ;Test to see if the modified SIN% jsys is available. Read in a string ; containing a control character and see if the jsys terminates on it. CHKSIN: BPL A,<134> ; Bell is second char BPM B,SPARE ; Point to some area MOVEI C,4 ; The whole string MOVX D,SI%TCC ; Special JSYS flag SIN% ; Start reading SKIPE C ; Did we stop on the ^g? FLGON F.NSIN ; Yes, new sin% available RET Subttl Number input routines ;Routine to read in a number from the screen. Gives skip return if ;it found one. GETNUM: CALL ICHAR ; Get a character SUBI A,60 ; Make into an integer JUMPLE A,GETN.A ; Return if non-positive CAIG A,11 ; Nine is highest allowed RETSKP ; Success ;Here if the number is illegal -- return it to it's previous value GETN.A: ADDI A,60 ; Return to normal RET ; And return ;Routine to read in a number with an optional minus. Returns the number ;in T1 and the terminator in T2. GETNIN: MOVEI A,.CTTRM ; Terminal RFMOD% ; Get mode MOVEM B,T3 ; Store the value TXZ B,TT%ECO ; Turn off the echo SFMOD% MOVEI A,.PRIIN ; Input MOVEI C,12 ; In decimal NIN% ; Get a number SETZ B, ; Failed, clear number MOVE T1,B ; Copy the number MOVEI A,.PRIIN ; In case of failure above BKJFN% ; Back up the terminator SKIPA A,14 ; Load a form feed PBIN% ; Get terminator CAIL A,"a" ; Check for lower case CAILE A,"z" TRNA ; No, skip SUBI A,SP ; Yes, convert to upper MOVE T2,A ; Copy it JRST GTNI.B ; Skip over the clear ;Restore echo and return GTNI.A: SETZ T1, ; Clear number GTNI.B: MOVEI A,.CTTRM ; Terminal MOVE B,T3 ; Old mode SFMOD% ; Restore RET ; And return ;Terminal special effects control SPCON: SKPON F.SPEF ; Special effeects? RET ; No SETSKP F.SPON ; Turn on special effects RET ; They were on already MOVE A,TJFN ; Terminal jfn MOVE C,[SEQ] SKPOFF F.ANSI ; Ansi terminal? MOVE C,[SEQ] ; Yes HLRZ B,C ; Get address HRLI B,441000 ; Byte pointer HRRES C ; Get count of chars in c SOUT% ; Type the string RET ; Done SPCOFF: SKPON F.SPEF ; Special effects? RET ; No CLRSKS F.SPON ; Turn off special effects RET ; They weren't on MOVE A,TJFN ; Get terminal jfn SKPOFF F.ANSI ; Ansi terminal? JRST SPCF.A ; Yes, handle differently MOVEI B,CL(O) ; Get the character BOUT% ; Send it RET ; And return SPCF.A: MOVE C,[SEQ] ; String to turn off attributes HLRZ B,C ; Get address HRLI B,441000 ; Byte pointer HRRES C ; Get count of chars in c SOUT% ; Type the string RET ; Done ;Cursor on and off on a viewpoint terminal CURSOF: MOVE A,TJFN ; Terminal jfn MOVEI B,"W"-100 ; Control-w SKPON F.SPEF ; Special effects? RET ; No SKPON F.ANSI ; Ansi terminal? BOUT% ; No, must be a viewpoint RET ; Done CURSON: MOVE A,TJFN ; Terminal jfn MOVEI B,"X"-100 ; Control-X SKPON F.SPEF ; Special effects? RET ; No SKPON F.ANSI ; Ansi terminal? BOUT% ; No, must be a viewpoint RET ; Done ;GETSTR - Read in an input string from the terminal into SPARE ; A points to the prompting string to be displayed ; GETSTU is an alternate entry that raises case of input. GETSTR: SKIPA B,[RD%BEL!RD%CRF!^D156] ; No raise by default GETSTU: MOVX B,RD%BEL!RD%CRF!RD%RAI!^D156 ; 156 chars max STKVAR <> ; Place to save acs HRLI A,440700 ; Make it a real pointer DMOVEM A,ACSTRG ; Save the acs DMOVE B,CCSTRG ; Save them XORI B,140000 ; Prevent lf from echoing literally TRO C,600000 ; Simulate format action for escape MOVEI A,.CTTRM ; Controlling terminal SFCOC% ; Reset it MOVEI B,.MOSLW ; Set terminal line width MOVE C,WIDTH ; To old value MTOPR% SETZ B, ; Line and column zero SFPOS% ; Set file position MOVE A,ACSTRG ; Restore the pointer PSOUT% ; Type the string MOVEI A,.CTTRM ; Get terminal RFPOS% ; Read our new position HRRZ C,B ; Isolate column DMOVE A,ACSTRG ; Get pointer again SUB B,C ; Subtract length of prompt MOVE C,A ; Copy for re-prompt HRROI A,SPARE ; Storage RDTTY% ; Read the input SSTERR (,EXIT) TXNN B,RD%BTM ; Break terminated input? IBP A ; No, so move over one SETZ B, ; Clear an ac DPB B,A ; And terminate the string MOVEI A,.CTTRM ; This terminal DMOVE B,CCSTRG ; Get old modes SFCOC% ; Restore them MOVEI B,.MOSLW ; Set width SETZ C, ; To zero again MTOPR% RET ; Done ;Ermsg routine - type an error message in the workspace unless we're ; in expert mode. Ermsa entry is for a message that is always typed. ERMSG: SKIPE EXPERT ; Are we expert? RET ; Yes ERMSA: PUSH P,A ; Save string pointer CALL WRKSPC ; Clear a workspace area CALL SPCON ; On with effects POP P,A ; Restore string pointer PSOUT% ; Type it MOVEI A,HLDTIM ; Time to wait DISMS% ; Sleep before returning CALL SPCOFF ; Off with effects CALL CLRWRK ; Clear work space RET ; And return ;End of program END