;CBBS V3.5.0 CBBSSUB1.ASM - NON-DISK ROUTINES #1 ;10/17/81 14:48:28 ; LINKS TO CBBSSUB2 ; ; O O O O O O O O ; O O O O O O O ; CBBS O O O O O O O O .ASM ; O O O O O O ; O O O O O O O O O O O ; ;MOD LOG: (THRU 3.2 PUT IN "HISTORY") ; ;====> HISTORICAL COMMENTS SINCE 3.3 TO "HISTORY.033" ; ;N-O-T-E SUBROUTINES ALPHABETIZED 07/26/81 ;(I GOT TIRED OF LOOKING FOR 'EM) ; ; GETNUM GETVAR JUSTA JUST5 ; PRDEC RDLINE TYPEX ; ;-----> ROUTINE TO CHECK FOR ^C, K, OR S ; ;^C RETURNS ZERO INDICATOR; ^K ABORTS, ;AND JUMPS TO 'FUNCT' (OR ENCOMD IF IN MESSAGE ;ENTRY); ^S WAITS FOR NEXT CHR. ^S IS ;TESTED FOR 1ST, SO USER CAN TYPE ^S THEN ;^K OR ^C. ; CTLCKS CALL KEYCHR ;GET CHR cpi ' ' ;check for space bar jnz spc ;for message flagging mvi a,'F' spc ANI 1FH ;MAKE 'S' INTO ^S, ETC CPI 'S'-40H ;^S? CZ KEYIN ;YES, WAIT FOR NEXT KEY cpi ' ' jnz nspc mvi a,'F' ;for message flagging nspc ANI 1FH CPI 'K'-40H ;ABORT? JZ CTLK ;CHECK IF ENABLED CPI 'N'-40H ;SET NULLS? JZ SETNUL CPI 'C'-40H ;^C? (RET/ZERO SET) RET ; ;GOT ^N - INCREASE NULLS BY 5 ; SETNUL LDA NULLS ADI 5 STA NULLS ORA A ;SET <>0 ^C CHECK RET ; ;GOT ^K - SEE IF ENABLED ; CTLK LDA CTLKSW ANI 7FH ;TURN OF "PRINTING NO ^K" SW DCR A ;WAS IT 1? JZ NCTLK ; YES, DISALLOW DCR A ;2? JZ ENCOMD ; YES, RET. TO ENTER DCR A ;3? JZ RTVFE ; YES, END FLAGGED RTRV DCR A ;4? JZ ASKT1 ; YES, TO FIRST TIME Q. JMP DEFUNCT ; NO ; ;TYPE THE 'NO ^K PERMITTED' MSG ;UNLESS WE ARE CURRENTLY PRINTING IT ; NCTLK LDA CTLKSW ;ALREADY TYPING ORA A ; CAN'T ^K MSG? RM ; YES, RETURN XRI 80H ;TURN ON 80H STA CTLKSW PUSH H PUSH B LXI H,NOCTLK CALL TYPEM0 ;TYPE MSG POP B POP H LDA CTLKSW XRI 80H STA CTLKSW XRA A ;SO ^C ACTION TAKEN RET ; ;-----> ROUTINE TO EXTRACT NUMBER FROM 'ANSWER' ;AND CONVERT TO BINARY. ALSO JUST USED TO ;VALIDATE THAT A PROPER NUMBER HAS BEEN ENTERED. ; GETNUM LXI H,0 ;INIT RESULT LXI D,ANSWER-1 GNLP INX D LDAX D ;GET DIGIT CPI CR RZ ;RETURN IF DONE CPI ',' ;AS IN SUMMARY SEARCH? RZ CPI '0' ;VALID? JC GNBAD CPI '9'+1 JC GNOK GNBAD MVI A,CR ;GET C, THEN sta inbuf ;kill stacked lines call ilprt db '++INVALID NUMBER++',cr,lf,0 stc ret ; RNZ ; RETURN ; ;GOT "X", TOGGLE EXPERT MODE (U-N-L-E-S-S ; BEING CALLED FROM "HELP" COMMAND ; gnok LDA INHELP ;ARE WE SUI '0' ;MAKE NUMBER BINARY PUSH D MOV D,H MOV E,L DAD H ;X2 DAD H ;X4 DAD D ;X5 DAD H ;X10 ADD L ;ADD IN DIGIT MOV L,A POP D JNC GNLP ;CARRY? INR H ;ADD IN CARRY JMP GNLP ;LOOP UNTIL C/R ; ;-----> ROUTINE TO INPUT A VARIABLE ; ;READS FROM KEYBOARD UNLESS IT IS IN THE BUFFER ;FROM A PREVIOUS ';' SEPARATOR. TRANSLATES ;FROM LOWER TO UPPER CASE ; ;ENTRY POINT GETVARN READS FROM INBUF, AND ;DOESN'T TRANSLATE TO UPPER CASE, AND DOESN'T LOOK FOR ;SEMICOLONS TO SEPARATE LOGICAL LINES. ; ;CALLING SEQUENCE: ; CALL GETVAR ; DB 'MESSAGE TO BE PRINTED',0 ; DW ADDR OF VARIABLE 04; DW HELP MESSAGE # (-1 IF NONE) 03/04/81 MOD ; DB LENGTH OF VAR ;(ACTUAL VAR MUST BE 1 LONGER FOR THE CR) ; GETVARN MVI A,CR ;GET FLAG STA INBUF ;SHOW INPUT MUST BE READ STA INFLG ;SET FLAG FOR NO TRANSLATE JMP GETVAR2 ; ;SET INFLG TO 0 TO SHOW THAT ';' IS TO BE ;HANDLED, AND THAT MESSAGE IS TO BE TRANSLATED ;TO UPPER CASE ; GETVAR XRA A ;GET 0 STA INFLG GETVAR2 POP H ;GET MESSAGE ADDR SHLD GVREPT ;SAVE IF REPEAT REQUIRED 01; 01;FLUSH BUFFERS IF RUNNING UNDER FAST 01; 01 IF FAST 01 CALL FLUSH 01 ENDIF 01; GETVR LDA INBUF ;HAVE TO INPUT IT? CPI 0DH JNZ GETNOI ;GET WITH NO INPUT ;HAVE TO INPUT GETV00 CALL TYPEX ;TYPE MESSAGE PUSH H CALL RDLINE ;READ A COMMAND LINE POP H JMP GETV ;ANS IN BUFFER - SKIP PROMPT MSG GETNOI MOV A,M ;GET CHR INX H ;SKIP IT ORA A ;ZERO AT END OF MSG? JNZ GETNOI ; ;GET VARIABLE VALUE ; GETV MOV E,M ;GET LO ADDR INX H MOV D,M ;GET HI ADDR 04 INX H ;03/04/81 TEMP MOD - 04 INX H ; SKIP THE HELP # XCHG SHLD GVTRUNC ;SAVE FOR TRUNCATE PRINT XCHG INX H ;TO LENGTH MOV A,M ;LENGTH STA LENGTH MOV C,A INR C ;ADD IN FOR C/R INX H ;GET RETURN ADDR PUSH H ;SAVE FOR RETURN LXI H,INBUF MOV A,M STA FIRSTCH ;SAVE FOR CASE TEST ; ;MOVE MESSAGE FROM INBUF TO VARIABLE. ;STORE CR AT END OF DATA RETRIEVED ; GETMV LDA INFLG ;';' AND TRANSLATE? ORA A ;SET FLAGS MOV A,M ;GET CHR JNZ NOUC ;NOT TRANSLATING CPI ';' ;IS IT THE DELIMITER? JNZ GETND ;NO, NO DELIMITER MVI A,CR ;FAKE UP C/R GETND CPI '|' 06 JZ NOUC CPI 60H ;LOWER CASE CHR? JC NOUC ;NO ANI 5FH ;MAKE UPPER CASE NOUC STAX D ;SAVE IN OUTPUT INX D INX H CPI CR JZ GETMVD ;MOVE IS DONE DCR C ;TOO LONG? JNZ GETMV ;11/11/78 ADDED "TRUNCATE" DCX D ;BACK UP MVI A,CR STAX D ;TRUNCATE PUSH D ;SAVE C/R POINTER STA INBUF ;CANCEL STACKED LINES CALL ILPRT DB '++LINE > ',0 ;PRINT LENGTH IN DECIMAL LDA LENGTH CALL PRDEC ;PRINT (A) IN DECIMAL CALL ILPRT DB ' LONG - ' DB 'TRUNCATED: ',0DH,0AH,0 ;05/07/79 PRINT TRUNCATED DATA LHLD GVTRUNC POP D ;GET C/R POINTER CALL TRUNC TRUNCPR MOV A,M CPI CR JZ TRUNCQ ; " " CALL TYPE INX H JMP TRUNCPR ; ;====> TRUNC GENERAL PURPOSE TRUNCATE TO A SPACE ; HL = START OF C/R DELIMITED LINE ; DE = END OF LINE ; TRUNC PUSH H ;SAVE POINTER TRUNCCR MOV A,M CPI ' ' JNZ TRUNS MOV D,H ;SAVE ADDR MOV E,L ; TRUNS INX H CPI CR JNZ TRUNCCR STAX D ;SET AT LAST SPACE OR BACK ; WHERE IT WAS POP H RET ; ;PRINTED TRUNCATED ; TRUNCQ CALL ILPRT ;PRINT: DB CR,LF,'++Type T or press return to ' DB 'truncate, R to re-enter the line: ',0 CALL KEYIN ;GET CHAR PUSH PSW CALL TYPE ;ECHO IT CALL CRLF POP PSW ANI 5FH ;UPPER CASE LHLD GVREPT ;SETUP HL CPI 'R' JZ GETV00 ;RE-KEY IT CPI 'T' RZ ;KEEP IT TRUNCATED CPI CR MVI A,LF JZ TYPE JMP TRUNCQ ;REPEAT QUESTION ; ;ANSWER HAS BEEN MOVED - MOVE THE NEXT ENTRY ;IN INBUF UP TO THE FRONT. ; GETMVD LXI D,INBUF DCX H ;BACK UP TO CR OR ';' MOV A,M ;GET DELIM CPI CR ;REAL END? JZ GETMV2 ;JUST MOVE IN CR, RETURN INX H ;SKIP ';' GETMV2 MOV A,M ;GET CHR STAX D ;SAVE IT INX D INX H CPI CR ;MOVED ALL? JNZ GETMV2 05;MODS: ; ;CHECK IF "X" ENTERED, AND TOGGLE EXPERT ;MODE, AND RE-ASK QUESTION, IF SO. ; LHLD GVTRUNC ;POINT TO DATA MOV A,M ;GET FIRST CHAR ANI 5FH ;MAKE UPPER CASE CPI 'X' RNZ ;NOT X INX H ;POINT TO SECOND CHAR MOV A,M ;GET IT CPI CR ;IF NOT C/R, THEN RNZ ; RETURN ; ;GOT "X", TOGGLE EXPERT MODE (U-N-L-E-S-S ; BEING CALLED FROM "HELP" COMMAND ; LDA INHELP ;ARE WE "IN HELP"? ORA A RNZ ;YES, RETURN CALL TOGGLEX LHLD GVREPT JMP GETVR ;RE-ASK, HAVING FLIPPED X 05;END ; ;-----> RIGHT JUSTIFY MESSAGE NUMBER, FROM ;WHAT HL POINTS TO, TO "MSGNO" ; JUSTA LXI H,ANSWER ;COME FROM ANSWER JUST5 PUSH H ;SAVE POINTER XCHG ;SET UP DCX D ; FOR GETNUM CALL GNLP ;ENTR MIDDLE TO VALIDATE # J5CK POP H RC ;INVALID PUSH H MVI B,0FFH ;"-1" J5C INR B MOV A,M CPI ',' ;AS AT START OF SEARCH JZ J5C2 ; STRING? CPI CR INX H JNZ J5C J5C2 POP H MOV A,B CPI 5 JZ J5M ;END, MOVE IT CMC ;CARRY IF >5 RC ; RET IF TOO MANY J5R PUSH H ;SAVE POINTER MVI B,'0' ;INIT "PREV" CHAR ; ;MOVE THE # RIGHT ONE, PADDING '0' ON LEFT ; J5R1 MOV A,M ;GET CHAR MOV M,B ;STORE PREV MOV B,A ;SAVE FOR NEXT MOVE INX H CPI CR JNZ J5R1 MOV M,B ;STORE THE C/R JMP J5CK ;REPEAT IF NECESSARY ; ;MOVE # TO MSGNO ; J5M LXI D,MSGNO ;MOVE IT MVI B,5 ; TO JMP MOVE ; MSGNO ; ;====> PRINT (A) IN DECIMAL. ; ALSO STORES IT IN "DECNUM" ; PRDEC PUSH H LXI H,DECNUM MVI C,100 CALL PRDECS MVI C,10 CALL PRDECS ORI '0' MOV M,A ;SAVE LAST DIGIT POP H JMP TYPE ; ;PRINT DIGIT AS CONVERTED FROM BINARY TO DECIMAL ; PRDECS MVI B,'0'-1 PRDECL INR B ;BUMP ASCII SUB C JNC PRDECL ;SUBTRACT MADE IT ADD C ;BACK OUT LAST SUB PRDEC2 PUSH PSW ;SAVE NUMBER MOV A,B ;GET ASCII MOV M,A ;SAVE IN MEM INX H ;TO NEXT CALL TYPE ;TYPE IT POP PSW ;RESTORE PARTIAL # RET ; ; ;----> ROUTINE TO READ IN LINE TO INBUF ; (MAIN ENTRY 20 LINES DOWN) ; RDLNCU MVI A,'^' ;ECHO '^U' FOR ^U CALL TYPE MVI A,'U' CALL TYPE ; IF TTY MVI A,'^' CALL LOG MVI A,'U' CALL LOG MVI A,CR CALL LOG ;OUTPUT CR TO LOG ENDIF ; RDLNCR CALL CRLF ; ;====> RDLINE MAIN ENTRY POINT <==== ; RDLINE LDA BELLF ;PROMPT ANI 1 ; BELL REQD? MVI A,7 ;BELL CNZ TYPE MVI A,'?' CALL TYPE RDLP0 MVI B,1 ;CHR COUNT LXI H,INBUF RDLP CALL KEYIN ;GET A CHR ; RDLTEST MOV M,A ;SAVE STORING IT LATER ; ;09/13/81 TEST FOR USER-ASSIGNED VIDEO BACKSPACE ; PUSH H LXI H,BSCHAR CMP M POP H JZ RDVBS ;09/13/81 END ; ;TEST FOR NON-VIDEO DELETES CPI '_' ;ASCII BACK ARROW?? JZ RDDEL ;YES, TREAT AS DEL CPI 7FH ;DEL? JZ RDDEL ;GOT DEL CPI ' ' ;PRINTABLE? JC RDLNCTL ; NO, A CTL CHAR ; ;GOT PRINTABLE CHAR ; RDECHO INX H INR B ;SET MINUS IF JM RDFULL ;BUFFER IS FULL, ECHO BELL PUSH B ;SAVE CHR MOV B,A ; IN B LDA ECHOFLG ORA A MOV A,B ;GET CHR CNZ TYPE ;ECHO IF FDX, NOT IF HDX MOV A,B ;GET CHR POP B ; IF TTY CALL LOG ;LOG IT ENDIF ; ;IF AT 55 CHRS, ECHO A BELL, WHETHER PROMPT ; (BELL) FLAG IS ON OR NOT ; MOV A,B CPI 50 ;was 55 JNZ RDLP JMP RDBELL ; ;BUFFER IS FULL - ECHO BELL, BACK UP ; RDFULL DCR B ;05/07/79 ADDED DCX H ;BACK UP POINTER RDBELL MVI A,7 CALL TYPE JMP RDLP ;BACK UP ; ;====> PROCESS ALL CONTROL CHARACTERS <==== ; RDLNCTL CPI 'E'-40H JZ RDCTLE ;LOGICAL C/R CPI 'H'-40H JZ RDVBS ;VIDEO BACKSPACE CPI 'I'-40H JZ RDTAB CPI 'K'-40H ;ABORT? JZ RDCTLK CPI 'L'-40H ;"WHAT COL AM I IN?" JZ RDCHCT CPI 'M'-40H ;(C/R?) JZ RDLCR ;YES, DONE CPI 'R'-40H ;^R? JZ RDCTLR CPI 'U'-40H ;^U? JZ RDLNCU CPI 'W'-40H JZ RDDELW ;WORD BACKSPACE CPI 'X'-40H JZ RDDELX ; ;UNKNOWN CONTROL CHARACTER ; JMP RDLP ;IGNORE IT ; ;====> CONTROL CHAR PROCESSING IN RDLINE ; ; ;DEL/'_' NON-VIDEO CHAR DELETE. ; ECHO CHARS BETWEEN '\'S ; RDDEL DCR B ;ALREADY AT FRONT? JZ RDLP0 ; YES, NO ECHO INR B CALL RDBKS ;ECHO & LOG '\' RDDELL DCX H DCR B JZ RDDELB ;BACKED UP TO BEGINNING ; IF TTY MOV A,M CALL LOG ENDIF ; MOV A,M ;GET DELETED CHAR CALL TYPE ; ECHO IT ; ;GET NEXT CHR, KEEP DELETING IF IT'S A DEL ; CALL KEYIN CPI 7FH JZ RDDELL ;KEEP ECHOING ; CPI 8 ;ASCII BKSP? ; JZ RDDELL CPI '_' JZ RDDEL ;O O O O O O push psw call rdbks pop psw jmp rdltest ; RDDELB CALL RDBKS ;TYPE '\' JMP RDLP0 ; ;SEND '\' TO USER AND LOG ; RDBKS EQU $ MVI A,'\' CALL TYPE ; IF TTY LOGDEL MVI A,'\' CALL LOG ;LOG ALL DELETES ENDIF ; RET ; ;SEND BACKSPACE-SPACE-BACKSPACE TO VIDEO ; TERMINAL TO ENSURE CHAR IS ERASED ; RDBSB MVI A,8 ;ASCII BS ' ' BS CALL TYPE CALL SPACE IF TTY CALL LOGDEL ;LOG DELETED CHAR ENDIF MVI A,8 JMP TYPE ; ;^E LOGICAL C/R ; RDCTLE CALL CRLF JMP RDLP ; ;^H VIDEO BACKSPACE ; RDVBS DCR B JZ RDLP0 ;AT FRONT ALREADY CALL RDBSB ;BS/SPACE/BS DCX H JMP RDLP ; ;^I TAB ; RDTAB CALL SPACE MVI M,' ' INX H INR B JM RDFULL MOV A,B DCR A ANI 7 JNZ RDTAB JMP RDLP ; ;^K ABORT IF AT START OF LINE ; RDCTLK MOV A,B ;GET COUNT DCR A ;AT START? JNZ RDLP ; NO, IGNORE IT LDA CTLKSW ;SEE IF ^K ORA A ; PERMITTED JNZ RDLP ;NOT PERMITTED, IGNORE ; ;^K PERMITTED. ECHO IT, AWAIT C/R ; MVI A,'^' CALL TYPE MVI A,'K' CALL TYPE CALL KEYIN CPI 'U'-40H JZ RDLNCU CPI CR JZ DEFUNCT ;KILL INBUF, GO TO FUNCT JMP RDLTEST ;PROCESS THE CHAR ; ;^L TYPE CURRENT LINE CHAR COUNT ; RDCHCT CALL CRLF PUSH B MOV A,B DCR A CALL PRDEC CALL SPACE POP B JMP RDLP ; ;^M (C/R) ; RDLCR CALL CRLF ; IF TTY MVI A,CR JMP LOG ENDIF ; RET ;BUFFER HAS BEEN READ ; ;^R RETYPE LINE ; RDCTLR PUSH B PUSH H CALL CRLF MVI B,'R'-40H ;ENDING CHAR LXI H,INBUF ;PRINT CALL TYPEM ; THE BUFFER POP H POP B JMP RDLP ; ;^W: VIDEO WORD DELETE ;^X: VIDEO LINE DELETE ; RDDELW MVI C,1 ;SHOW IN WORD BACKSPACE JMP RDDELWX ; RDDELX MVI C,0 ;SHOW NOT END OF WORD ; RDDELWX DCR B ;BACK TO BEGINNING? JZ RDLP0 ;YES DCX H PUSH B ;TYPING CLOBBERS C CALL RDBSB ;BS/SP/BS CALL CTLCKS ;ALLOW ABORT FROM POP B JZ RDLP ; ^2-ING A LONG WORD MOV A,C ;ARE WE ORA A ; LINE BACKSPACING? JZ RDDELWX ; YES. DCX H ;HAVE WE MOV A,M ; BACKED UP INX H ; TO CPI ' ' ; A ' ' JZ RDLP ; (YES) CPI ';' ; OR ';'? JZ RDLP ; (YES) JMP RDDELWX ; (NO), LOOP ; ;ROUTINE TO TYPE BUFFER, AS IN WHEN A ;QUESTION IS ASKED. IF THE 'EXPERT USER' FLAG ;IS SET, THEN IT STOPS AT THE FIRST ':' IN ;THE MESSAGE. ; TYPEX LDA EXPERT ;EXPERT USER? ORA A JZ TYPEM0 ;NO, JUST TYPE LINE TYPEX2 MOV A,M ;GET CHAR INX H ORA A ;END (=0)? RZ ;YES, RET PUSH PSW CALL TYPE POP PSW CPI ':' JNZ TYPEX2 ;END OF EXPERT PROMPT, SKIP TO END OF MSG TYPEX3 MOV A,M INX H ORA A JNZ TYPEX3 RET ; LINK CBBSSUB2 ;TO NEXT .ASM FILE