{This version of NSB is for use with the Zenith Z-19/Heath H-19 terminals. The SB_GETCH function has been modified to intercept the Escape sequence commands so that the 18 keypad & special function keys can be used. All original commands still function as before, except that the ERASE key is now the escape (ESC) key. The ESC key still functions but must be pushed twice in succession to obtain an escape. Ron Finger Ficomp, Inc. 3017 Talking Rock Dr. Fairfax, VA 22031 (703)280-1394 } { VERSION 0058 } {$K0} {$K1} {$K2} {$K5} {$K6} {$K7} {$K8} {$K12} {$K13} {$K14} {$K15} PROGRAM PASCAL_SPP; {$I EDTYPES} {$I EDGLBLS} TYPE CPMOPERATION = (COLDBOOT,WARMBOOT,CONSTAT,CONIN,CONOUT,LIST, PUNOUT,RDRIN,HOME,SELDSK,SETTRK,SETSEC,SETDMA, DSKREAD,DSKWRITE); FNAME = ARRAY [1..8] OF CHAR; { CP/M FILE NAME } EXTENSION = ARRAY [1..3] OF CHAR; { EXTENSION TO NAME } FCB = RECORD DSK : BYTE; FN : FNAME; EXT : EXTENSION; OTHER: ARRAY [12..36] OF BYTE END; DIRENT = RECORD ET : BYTE; FN : FNAME; EXT : EXTENSION; OTHR : ARRAY [12..31] OF BYTE END; {$I SBIFDEF.LIB} VAR DIRFILE: FCB; { FOR DISPLAYING DIRECTORIES } DIRBUF: ARRAY [0..3] OF DIRENT; FSTRING: STRING; MEMORY: ABSOLUTE [$0000] ARRAY[0..0] OF BYTE; CMDCH: CHAR; @SFP: EXTERNAL INTEGER; BUFSTAT: STATREC; INTRFACE: SB_INTERFACE; { USED TO COMMUNICATE BETWEEN PROGRAMS } SB_LAST_X, SB_LAST_Y: INTEGER; { FOR SOFTWARE CLR TO EOL/ CLR TO EOS ROUTINES } EXTERNAL FUNCTION @BDOS(PARM,FUNC:INTEGER):INTEGER; EXTERNAL [1] PROCEDURE LOGWRITER; { LOG WRITER OVERLAY } EXTERNAL [2] PROCEDURE SPEED; { EDITOR OVERLAY } EXTERNAL [3] PROCEDURE SYNCHECK; { SYNTAX CHECKER OVERLAY } EXTERNAL [4] PROCEDURE VARCHECK; { UNDEF VAR CHECKER OVERLAY } EXTERNAL [6] PROCEDURE MTRUN; { RUN PROGRAM OVERLAY } EXTERNAL [7] PROCEDURE DISP_DIR; { DIRECTORY DISPLAY OVERLAY } EXTERNAL [8] FUNCTION GETFILE:BOOLEAN; { GET EDITOR FILE NAME, ETC. } EXTERNAL [8] PROCEDURE INIT; { EDITOR INIT } EXTERNAL [9] PROCEDURE EDITWRITE; { EDITOR WRITE BUFFER OVERLAY } EXTERNAL[10] PROCEDURE PRETTY; { PROGRAM REFORMATER } {--------------------------------------------------------------} { H-19/Z-19 terminal area BEGINS here: } {--------------------------------------------------------------} FUNCTION LINESZ : INTEGER; { SO USER CAN SET SIZE OF A LINE } BEGIN LINESZ := 79 { 80 - 1 } END; FUNCTION SCREENSZ : INTEGER; BEGIN SCREENSZ := 22 { NUMBER OF LINES ON PHYSICAL SCREEN - 2 } END; FUNCTION STATUSROW : INTEGER; BEGIN STATUSROW := SCREENSZ + 1 END; PROCEDURE SB_OUT_CH(CH:CHAR); BEGIN SB_BIOS_CALL(CONOUT,ORD(CH)) END; FUNCTION SB_GETCH:CHAR; {CONVERT H/Z-19 ESC SEQUENCE COMMANDS TO SPP EQUIV. Control character commands will function as before; For Escape - hit ESC twice in succession} VAR CH : CHAR; CHO : INTEGER; BEGIN SB_BIOS_CALL(CONIN,0); INLINE("STA / CH); IF ORD(CH)=$1B THEN {if ESC then get next char in sequence} BEGIN SB_BIOS_CALL(CONIN,0); INLINE("STA / CH); CASE CH OF {19 KEY CONTROL CHAR} 'V' : CHO := $03; { f4 ^C } 'P' : CHO := $06; { blue ^F } 'N' : CHO := $07; { DC ^G } 'D' : CHO := $08; { arrow left ^H } 'B' : CHO := $0A; { arrow down ^J } 'A' : CHO := $0B; { arrow up ^K } 'C' : CHO := $0C; { arrow right ^L } 'L' : CHO := $0E; { IL ^N } 'R' : CHO := $11; { white ^Q } 'W' : CHO := $12; { f5 ^R } 'T' : CHO := $13; { f2 ^S } 'H' : CHO := $14; { HOME ^T } 'U' : CHO := $15; { f3 ^U } 'Q' : CHO := $16; { red ^V } 'S' : CHO := $17; { f1 ^W } 'M' : CHO := $19; { DL ^Y } '@' : CHO := $1A; { IC ^Z } 'J' : CHO := $1B; { ERASE ESC } ELSE CHO := ORD(CH) END; {CASE} SB_GETCH :=CHR(CHO) END ELSE SB_GETCH := CH END; PROCEDURE XYGOTO(X,Y:INTEGER); BEGIN SB_OUT_CH(CHR(ESC)); SB_OUT_CH('Y'); SB_OUT_CH(CHR(Y+32)); SB_OUT_CH(CHR(X+32)); SB_LAST_X := X; SB_LAST_Y := Y; { THESE ARE USED ONLY BY USER SOFTWARE } { ROUTINES WHICH PERFORM CLR TO EOS AND } { CLR TO EOL } END; PROCEDURE SB_CLR_SCRN; BEGIN SB_OUT_CH(CHR(ESC)); SB_OUT_CH('E') END; PROCEDURE SB_CLR_EOS; BEGIN SB_OUT_CH(CHR(ESC)); SB_OUT_CH('J'); SB_OUT_CH(CHR(0)); { GIVE IT TIME TO WORK } SB_OUT_CH(CHR(0)); { GIVE IT TIME TO WORK } SB_OUT_CH(CHR(0)); { GIVE IT TIME TO WORK } SB_OUT_CH(CHR(0)); { GIVE IT TIME TO WORK } END; PROCEDURE SB_CLR_LINE; BEGIN SB_OUT_CH(CHR(ESC)); SB_OUT_CH('K'); END; {--------------------------------------------------------------} { User modification area ENDS WITH SB_CLR_LINE } {--------------------------------------------------------------} PROCEDURE SB_FLUSH_BUF; VAR CH : CHAR; BEGIN IF NOT BUFSTAT.OCCUPIED THEN EXIT; REPEAT PRNT_AT(20,1,'Buffer occupied'); PRNT_AT(21,1,'F)lush, U)pdate, W)rite & Flush, L)eave:'); CH := SB_UP_CASE(SB_GETCH); SB_OUT_CH(CH); IF CH = 'L' THEN EXIT; IF CH = 'F' THEN BEGIN IF NEWFILE THEN PURGE(F); BUFSTAT.OCCUPIED := FALSE; EXIT END; IF CH = 'W' THEN BEGIN EDITWRITE; LOGWRITER; BUFSTAT.OCCUPIED := FALSE END; IF CH = 'U' THEN BEGIN EDITWRITE; { BUT LEAVE IT OCCUPIED } LOGWRITER END UNTIL (CH='U') or (CH='F') OR (CH='W'); NEWFILE:=FALSE; END; PROCEDURE SB_BIOS_CALL(FUNC:CPMOPERATION; PARM:INTEGER); VAR DISPATCH_LOC : INTEGER; BEGIN DISPATCH_LOC := (MEMORY[1] + SWAP(MEMORY[2])) + (ORD(FUNC)*3) - 3; INLINE("LHLD / PARM / "MOV C,L / "MOV B,H / "LHLD / DISPATCH_LOC / "PCHL); END; PROCEDURE PRNT_AT(ROW,COL:INTEGER; S:STRING); BEGIN XYGOTO(COL,ROW); WRITE([ADDR(SB_OUT_CH)],S) END; PROCEDURE MENU; BEGIN SB_CLR_SCRN; PRNT_AT(1,1,'SpeedProgramming Package V5.2'); PRNT_AT(3,1,'Options: E)dit'); prnt_at(4,20, 'R)eformat'); prnt_at(5,20, 'S)yntax check'); prnt_at(6,20, 'V)ar check'); prnt_at(7,20, 'X)eq'); prnt_at(8,20, 'D)ir'); prnt_at( 9,20, 'L)ink'); prnt_at(10,20, 'F)ast compile'); prnt_at(11,20, 'Q)uit'); prnt_at(22,1,'Command? ') END; FUNCTION SB_UP_CASE(CH:CHAR):CHAR; BEGIN IF (CH >= 'a') AND (CH <= 'z') THEN SB_UP_CASE := CHR(CH & $DF) ELSE SB_UP_CASE := CH END; {$E-} FUNCTION GET_FILE_INTO_BUF:BOOLEAN; BEGIN IF NOT BUFSTAT.OCCUPIED THEN IF GETFILE THEN { GET FILE INTO BUFFER } INIT; GET_FILE_INTO_BUF := BUFSTAT.OCCUPIED END; {$E+} BEGIN SB_OUT_CH(CHR(ESC)); {set up block cursor} SB_OUT_CH('x'); SB_OUT_CH('4'); BUFSZ := (@SFP - ADDR(BUF))-$100; { SET UP EDITOR BUFFER SIZE } BUFSTAT.OCCUPIED := FALSE; NEWFILE := FALSE; REPEAT MENU; INTRFACE.NEXT_CMD := ' '; { DEFAULT NO NEXT PROGRAM } INTRFACE.END_STAT := OK; CMDCH := SB_UP_CASE(SB_GETCH); SB_OUT_CH(CMDCH); { ECHO IT } REPEAT FSTRING := ''; { DEFAULT IS NO PROGRAM } CASE CMDCH OF 'D' : DISP_DIR; 'E' : BEGIN IF (BUFSTAT.OCCUPIED) AND ((INTRFACE.PREV_CMD = 'S') OR (INTRFACE.PREV_CMD = 'R'))THEN { DO NOTHING } ELSE SB_FLUSH_BUF; { MAKE SURE USER WANTS TO DO THIS } IF NOT BUFSTAT.OCCUPIED THEN { BUFFER IS EMPTY } BEGIN IF GETFILE THEN { SEE IF HE WANTS A FILE } BEGIN INIT; { CALL EDITOR } IF BUFSTAT.OCCUPIED THEN SPEED END END ELSE SPEED; { BUFFER OCCUPIED, EDIT OLD } INTRFACE.PREV_CMD := ' '; IF INTRFACE.NEXT_CMD = 'E' THEN INTRFACE.NEXT_CMD := ' '; END; 'S' : BEGIN IF GET_FILE_INTO_BUF THEN BEGIN INTRFACE.PREV_CMD := ' '; SYNCHECK; IF INTRFACE.END_STAT = SYNERR THEN INTRFACE.NEXT_CMD := 'E' END END; 'V' : IF GET_FILE_INTO_BUF THEN VARCHECK; 'R' : BEGIN IF GET_FILE_INTO_BUF THEN BEGIN INTRFACE.PREV_CMD := 'R'; PRETTY; INTRFACE.NEXT_CMD := 'E'; SB_CLR_SCRN END END; 'X' : BEGIN SB_FLUSH_BUF; FSTRING := ''; MTRUN END; 'Q' : BEGIN INTRFACE.PREV_CMD := ' '; SB_FLUSH_BUF; IF BUFSTAT.OCCUPIED THEN CMDCH := '@' ELSE BEGIN SB_CLR_SCRN; EXIT END END; 'L' : BEGIN SB_FLUSH_BUF; FSTRING := 'L'; {new linker is just 'L' } MTRUN END; 'F' : BEGIN IF GET_FILE_INTO_BUF THEN BEGIN SB_FLUSH_BUF; FSTRING := 'FASTCOMP'; MOVE(ENDFILE,MEMORY[ADDR(BUF)-2],2);{ SET UP INTEGER } MOVE(NAME,MEMORY[ADDR(BUF)-83],81); MTRUN END END END; CMDCH := INTRFACE.NEXT_CMD; UNTIL (CMDCH = ' ') OR (CMDCH = INTRFACE.PREV_CMD); UNTIL FALSE END.