(*$L #5:SCUNIT.LST.TEXT*) (*$S+*) UNIT SCUNIT; (*Copyright 1980 Kenneth L. Bowles, All rights reserved. Permission is hereby granted to use this material for any non-commercial purpose*) (*This version includes specific constants for Terak 8510A*) INTERFACE TYPE SCCHSET = SET OF CHAR; SCKEYCOMMAND = (BACKSPACEKEY,ETXKEY,ESCKEY,DELKEY,UPKEY,DOWNKEY, LEFTKEY,RIGHTKEY,NOTLEGAL); VAR SCCH:CHAR; PROCEDURE SCINITIALIZE; PROCEDURE SCLEFT; PROCEDURE SCRIGHT; PROCEDURE SCUP; PROCEDURE SCDOWN; PROCEDURE SCGETCCH(VAR CH:CHAR; OKSET:SCCHSET); FUNCTION SCMAPCRTCOMMAND(KCH: CHAR): SCKEYCOMMAND; PROCEDURE SCREADSTRG(VAR S:STRING; WIDTH:INTEGER; CCHSET:SCCHSET; ROW,COL:INTEGER); PROCEDURE SCREADINT(VAR X: INTEGER; WIDTH:INTEGER; ROW,COL:INTEGER); IMPLEMENTATION CONST SCEOL=13; BELL=7; UNDERLINE='_'; VAR TRANSLATE: PACKED ARRAY[CHAR] OF SCKEYCOMMAND; KEYBRD: PACKED ARRAY[SCKEYCOMMAND] OF CHAR; PROCEDURE SCINITIALIZE; VAR I:INTEGER; BEGIN FOR I:=0 TO 255 DO TRANSLATE[CHR(I)]:=NOTLEGAL; TRANSLATE[CHR(8)]:=BACKSPACEKEY; KEYBRD[BACKSPACEKEY]:=CHR(8); TRANSLATE[CHR(3)]:=ETXKEY; KEYBRD[ETXKEY]:=CHR(3); TRANSLATE[CHR(26)]:=UPKEY; KEYBRD[UPKEY]:=CHR(26); TRANSLATE[CHR(12)]:=DOWNKEY; KEYBRD[DOWNKEY]:=CHR(12); TRANSLATE[CHR(23)]:=LEFTKEY; KEYBRD[LEFTKEY]:=CHR(23); TRANSLATE[CHR(11)]:=RIGHTKEY; KEYBRD[RIGHTKEY]:=CHR(11); KEYBRD[ESCKEY]:=CHR(27); KEYBRD[DELKEY]:=CHR(127); END (*INITIALIZE*); FUNCTION SCMAPCRTCOMMAND(*(VAR KCH:CHAR): SCKEYCOMMAND*); BEGIN SCMAPCRTCOMMAND:=TRANSLATE[KCH] END; PROCEDURE SCLEFT; BEGIN WRITE(CHR(8)); END (*SCLEFT*); PROCEDURE SCRIGHT; BEGIN WRITE(CHR(28)); END (*SCRIGHT*); PROCEDURE SCUP; BEGIN WRITE(CHR(31)); END (*SCUP*); PROCEDURE SCDOWN; BEGIN WRITE(CHR(10)); END (*SCDOWN*); PROCEDURE SQUAWK; BEGIN WRITE(CHR(BELL)); END; PROCEDURE SCGETCCH(*VAR CH: CHAR; OKSET: SCCHSET*); BEGIN REPEAT (*If user wants a character then get one that's LEGAL*) READ(KEYBOARD,CH); IF EOLN(KEYBOARD) THEN CH:=CHR(SCEOL); IF NOT (CH IN OKSET) THEN SQUAWK; UNTIL (CH IN OKSET); END; PROCEDURE UCLC(VAR CH:CHAR); BEGIN IF CH IN ['a'..'z'] THEN CH:=CHR(ORD(CH)-32); END (*UCLC*); PROCEDURE FILLFIELD(CH:CHAR; WIDTH:INTEGER); (*fill a field on screen with CH by fastest method (in practice) *) VAR A:PACKED ARRAY[0..79] OF CHAR; BEGIN FILLCHAR(A[0], WIDTH, CH); WRITE(A:WIDTH); END (*FILLFIELD*); PROCEDURE TRUNCSTRING(WIDTH:INTEGER; INSTRG:STRING; VAR OUTSTRG: STRING); BEGIN IF LENGTH(INSTRG)<=WIDTH THEN OUTSTRG:=INSTRG ELSE OUTSTRG:=COPY(INSTRG,1,WIDTH); END (*TRUNCSTRG*); (*$G+*) PROCEDURE SCREADSTRG(*VAR S:STRING; WIDTH:INTEGER; CCHSET:SCCHSET; ROW,COL:INTEGER*); (*this is (hopefully) a reasonably friendly string read to replace the standard routine in the system*) (*display S, with underlining to fill out remainder of WIDTH columns. allow editing within the displayed field. See embedded comments regarding edit commands.*) LABEL 2; VAR CH:CHAR; X:STRING[1]; CURSINX,CHCNT:INTEGER; CHOK:SCCHSET; TS,TAILS:STRING; BEGIN X:=' '; TS:=S; CHCNT:=LENGTH(TS); GOTOXY(COL,ROW); IF LENGTH(TS) > WIDTH THEN DELETE(TS,WIDTH+1, (WIDTH-LENGTH(TS))); WRITE(TS); IF LENGTH(TS) < WIDTH THEN FILLFIELD(UNDERLINE, WIDTH - LENGTH(TS)); GOTOXY(COL,ROW); CURSINX:=1; CHOK:=CCHSET + [CHR(SCEOL), KEYBRD[ESCKEY], KEYBRD[RIGHTKEY], KEYBRD[LEFTKEY], KEYBRD[BACKSPACEKEY], KEYBRD[DELKEY] ]; REPEAT SCGETCCH(CH,CHOK); IF CH=KEYBRD[ESCKEY] THEN BEGIN (*restore previous string to screen & bail out*) GOTOXY(COL,ROW); FILLFIELD(' ',WIDTH); GOTOXY(COL,ROW); WRITE(S); GOTO 2; END; IF CH IN [KEYBRD[BACKSPACEKEY], KEYBRD[LEFTKEY] ] THEN BEGIN (*move cursor left one position*) IF CURSINX > 1 THEN BEGIN SCLEFT; CURSINX:=CURSINX-1; END; END ELSE IF CH=KEYBRD[RIGHTKEY] THEN BEGIN (*move cursor right one position*) IF (CURSINX < (CHCNT+1)) AND (CURSINX < WIDTH) THEN BEGIN SCRIGHT; CURSINX:=CURSINX+1; END; END ELSE IF CH=KEYBRD[DELKEY] THEN BEGIN (*delete one character, redisplay the tail*) IF CHCNT > 0 THEN BEGIN DELETE(TS,CURSINX,1); CHCNT:=CHCNT-1; TAILS:=TS; IF CURSINX > 1 THEN DELETE(TAILS,1,CURSINX-1); WRITE(TAILS); WRITE(UNDERLINE); GOTOXY((COL+CURSINX-1),ROW); END; END ELSE IF CH <> CHR(SCEOL) THEN (*insert the character and redisplay the tail*) IF CHCNT < WIDTH THEN BEGIN X[1]:=CH; INSERT(X,TS,CURSINX); CHCNT:=CHCNT+1; TAILS:=TS; DELETE(TAILS,1,CURSINX-1); WRITE(TAILS); (*only the tail needs to be rewritten*) IF CURSINX < WIDTH THEN CURSINX:=CURSINX+1; GOTOXY((COL+CURSINX-1),ROW); END; UNTIL (CH = CHR(SCEOL)); S:=TS; 2: END (*SCREADSTRG*); PROCEDURE SCREADINT(*VAR X: INTEGER; WIDTH:INTEGER; ROW,COL:INTEGER*); (*read integers in as friendly a way as possible - without blowing up*) (*This is for reading 16 bit integers - not long integers*) LABEL 1,2; CONST BADINT= -32767; VAR NUM,PCH,PWRTEN,DIGIT:INTEGER; CH:CHAR; NEGATIVE,DONE:BOOLEAN; S:STRING[7]; BEGIN GOTO 2; (*Jump over error handling*) 1: GOTOXY(COL,ROW); FOR PCH:=1 TO WIDTH DO WRITE('*'); SQUAWK; 2: S:=''; SCREADSTRG(S,WIDTH,[' ','-','+','0'..'9'],ROW,COL); NUM:=0; PWRTEN:=1; PCH:=1; NEGATIVE:=FALSE; DONE:=FALSE; X:=BADINT; (*Strip off leading blanks*) WHILE (LENGTH(S)>0) AND (NOT DONE) DO IF S[1]=' ' THEN DELETE(S,1,1) ELSE DONE:=TRUE; IF LENGTH(S)>0 THEN BEGIN IF S[1] IN ['+','-'] THEN BEGIN NEGATIVE:=(S[1]='-'); DELETE(S,1,1); END; PCH:=LENGTH(S); WHILE (PCH>=1) AND (NUM<10000) DO BEGIN IF S[PCH] IN [' ','+','-'] THEN GOTO 1 ELSE DIGIT:=ORD(S[PCH])-ORD('0'); IF NUM>1000 THEN CASE S[PCH] OF '0','1','2': NUM:=NUM+DIGIT*PWRTEN; '3': IF NUM<=2767 THEN NUM:=NUM+30000 ELSE GOTO 1; '4','5','6','7','8','9': GOTO 1 END (*CASES*) ELSE NUM:=NUM+DIGIT*PWRTEN; PWRTEN:=PWRTEN*10; PCH:=PCH-1; END (*WHILE*); IF NEGATIVE THEN X:=-NUM ELSE X:=NUM; END (*LENGTH(S)>0*); END (*READINT*); END.