* PROGRAM NAME: HELP * AUTHOR: RICHARD CONN * DATE: 6 OCT 80 * VERSION: 1.1 * PREVIOUS VERSIONS: 1.0 (18 NOV 79) ***************************************************************** * * * HELP -- DISPLAY HELP FILE INFORMATION TO USER ON CON: * * * * THE HELP COMMAND IS OF THE GENERAL FORM: * * HELP . * * * * . IS OPTIONAL; IF OMITTED COMPLETELY, * * 'HELP.HLP' IS ASSUMED; IF JUST IS OMITTED, EXTENSION * * IS ASSUMED TO BE '.HLP' * * * * THE HELP COMMAND DISPLAYS THE INFORMATION IN A HELP * * FILE TO THE USER. THERE ARE TWO BASIC TYPES OF HELP FILES -- * * (1) INDEXED AND (2) NON-INDEXED. INDEXED HELP FILES ARE * * THOSE WHICH CONTAIN SEVERAL SECTIONS; THE INDIVIDUAL MAY * * READ ALL OF SUCH A HELP FILE OR JUST SELECTED SECTIONS OF * * THIS FILE. NON-INDEXED HELP FILES CONTAIN ONLY ONE SECTION. * * STRUCTURALLY SPEAKING, HELP FILES CONSIST OF TWO PARTS: * * THE HEADER PART AND THE INFORMATION PART. THE INFORMATION * * PART OF A HELP FILE BEGINS WITH A LINE WHOSE FIRST CHARACTER * * IS A COLON. THE TITLE OF THE INFORMATION SECTION IS ON THIS * * LINE. THE INFORMATION SECTION CONTINUES UNTIL THE NEXT * * INFORMATION SECTION (LINE STARTING WITH A COLON) OR THE END * * OF THE FILE IS ENCOUNTERED. THE HEADER PART CONSISTS OF A * * GROUP OF LINES BEFORE THE FIRST INFORMATION SECTION. IF THE * * FIRST LINE OF A HELP FILE STARTS WITH A COLON, THEN THERE IS * * NO HEADER PART, AND THE HELP FILE IS DUMPED AS ONE * * INFORMATION SECTION. * * THERE MUST BE THE SAME NUMBER OF LINES IN THE HEADER * * PART AS THERE ARE INFORMATION SECTIONS. IF NOT, A HELP * * FILE ERROR WILL BE ISSUED IF THE HELP COMMAND ATTEMPTS TO * * READ BEYOND THE END OF THE HELP FILE IN ITS SEARCH FOR AN * * INFORMATION SECTION. * * * ***************************************************************** ***************************************************************** * * * THE HELP PROGRAM IS COMPLETELY TRANSPORTABLE BETWEEN CP/M * * SYSTEMS. * * * ***************************************************************** ***************************************************************** * CP/M AND BASIC CHARACTER DEFINITIONS * ***************************************************************** BDOS EQU 5 ; ADDRESS OF BDOS ENTRY POINT FCB EQU 5CH ; ADDRESS OF FILE CONTROL BLOCK BUFF EQU 80H ; ADDRESS OF DMA BUFFER CR EQU 0DH ; LF EQU 0AH ; FF EQU 'L'-40H ; CTRL-L = FORM FEED CTRLZ EQU 'Z'-40H ; CTRL-Z CTRLC EQU 'C'-40H ; CTRL-C ***************************************************************** * CHARACTER WHICH MARKS START OF INFORMATION SECTION * ***************************************************************** SECT$CHAR EQU ':' ; DEFINED TO BE COLON ALL$CHAR EQU '*' ; ALL OF HELP FILE DESIGNATOR ***************************************************************** * USER CUSTOMIZATION -- LINES PER SCREEN DISPLAY * ***************************************************************** LINES$PER$SCREEN EQU 24 ; ASSUME 24 LINES/SCREEN ***************************************************************** * START OF PROGRAM * ***************************************************************** ORG 100H START: LXI H,0 ; GET SP DAD SP SHLD STACK XRA A ; TURN OFF DEFAULT FILE FLAG STA DFFLG LXI D,HELPMS ; PRINT OPENING MSG CALL PRINT$MESSAGE LXI H,FCB+1 ; CHECK FOR FILE NAME MOV A,M CPI ' ' ; NONE? JZ DEFAULT$FN ORA A ; ALSO NONE JNZ START1 * INSERT 'HELP.HLP' INTO FCB DEFAULT$FN: DCX H ; PT TO FCB LXI D,DEFFN MVI B,12 ; 12 BYTES XCHG CALL MOVE ; MOVE (HL) TO (DE) FOR (B) BYTES MVI A,1 ; TURN ON DEFAULT FILE FLAG STA DFFLG JMP START2 * CHECK FOR EXTENSION TO FILE NAME START1: LXI H,FCB+9 ; CHECK FOR EXTENSION MOV A,M CPI ' ' ; NONE? JZ DEFAULT$EXT ORA A ; NONE ALSO JNZ START2 * PLACE DEFAULT EXTENSION OF '.HLP' IN FCB DEFAULT$EXT: LXI D,DEFEXT MVI B,3 XCHG CALL MOVE ; MOVE (HL) TO (DE) FOR (B) BYTES * OPEN FILE START2: LXI D,FCB ; PT TO FCB MVI C,15 ; OPEN FILE CALL BDOS CPI 255 ; NOT PRESENT? JNZ START3 * CHECK FOR DEFAULT FILE SEARCH LDA DFFLG ; GET DEFAULT FILE FLAG ORA A ; 1=YES, SEARCH FOR DEFAULT FAILED JNZ HELP ; DISPLAY DEFAULT HELP FILE INFORMATION * FILE NOT FOUND -- FATAL ERROR LXI D,ERR1 ; FILE NOT FOUND CALL PRINT$MESSAGE RET * LOAD HELP FILE INFORMATION START3: LXI H,HELP$BUF ; PT TO BUFFER SHLD NEXT$ADR ; SET PTR * READ RECORDS UNTIL EOF START4: CALL READ$RECORD ; READ INFO ORA A ; DONE? 0=NO JZ START4 * * START OF HELP PROGRAM * HELP: LXI SP,STACK ; RESET STACK LXI H,HELP$BUF ; PT TO BUFFER MOV A,M ; NO HEADER SECTION? CPI SECT$CHAR JNZ HELP1 ; HEADER SECTION EXISTS CALL PRINT$INFO ; PRINT HELP INFO PTED TO BY HL * EXIT POINT FOR ANY EXIT FROM THE REST OF THE HELP PROGRAM HELP$EXIT: LHLD STACK ; GET CP/M SP SPHL RET ; DONE * PRINT HEADER INFORMATION AND SELECT AN OPTION HELP1: CALL PRINT$HEADER ; PRINT HEADER LXI D,PROMPT$MESSAGE ; PRINT PROMPT CALL PRINT$MESSAGE CALL CHAR$IN ; GET RESPONSE CPI CTRLC ; RETURN TO CP/M JZ HELP$EXIT CPI ALL$CHAR ; ALL OF HELP FILE? JZ HELP$ALL ANI 0DFH ; CAPITALIZE PUSH PSW ; SAVE CHAR CALL CRLF1 POP PSW ; GET CHAR SUI 'A'-1 ; ADJUST FOR COUNT MOV B,A ; SAVE COUNT JZ BAD$RESPONSE JNC HELP2 * INVALID RESPONSE BAD$RESPONSE: LXI D,ERR2 ; INVALID RESPONSE CALL PRINT$MESSAGE JMP HELP1 * VALID RESPONSE -- LOOK FOR AND PRINT INFORMATION SECTION HELP2: INR C ; 1 MORE THAN NUMBER OF POSSIBLE SELECTIONS CMP C ; GREATER THAN NUMBER OF POSSIBLE SELECTIONS? JNC BAD$RESPONSE LHLD FIRST$ENTRY ; GET PTR TO FIRST ENTRY * PRINT INFORMATION WHEN COUNT IS ZERO HELP3: DCR B ; COUNT DOWN JNZ HELP4 INX H ; SKIP OVER COLON CALL PRINT$INFO ; PRINT INFO PTED TO BY HL JMP HELP1 * LOCATE NEXT INFORMATION SECTION HELP4: MOV A,M ; ? INX H ; PT TO NEXT BYTE CPI CTRLZ JZ HELP$ERR ; HELP FILE FORMAT ERROR CPI LF ; LINE FEED (WS FILE)? JZ HELP5 CPI CR ; ? JNZ HELP4 INX H ; 1ST BYTE OF NEXT LINE HELP5 MOV A,M ; GET CHAR CPI SECT$CHAR ; NEW SECTION? JZ HELP3 ; CONTINUE LOOP IF SO CPI CTRLZ ; EOF? JNZ HELP4 ; CONTINUE IF NOT * ERROR -- REACHED END OF HELP FILE HELP$ERR: LXI D,ERR3 ; FORMAT ERROR CALL PRINT$MESSAGE JMP HELP1 * PRINT ALL OF HELP FILE HELP$ALL: LHLD FIRST$ENTRY ; PT TO FIRST ENTRY CALL SET$LINE$CNT ; SET LINE COUNT * EXECUTE UNTIL A CTRL-Z IS ENCOUNTERED HA1: INX H ; SKIP OVER COLON CALL PI1 ; PRINT INFO W/OUT LINE CNT INFO MOV A,M ; GET LAST CHAR CPI CTRLZ JNZ HA1 JMP HELP ********************************************************* * * * HELP SUPPORT ROUTINE SECTION * * * ********************************************************* * * INPUT CHAR; CHAR IS IN A * CHAR$IN: PUSH B ! PUSH D ! PUSH H MVI C,1 ; READ CHAR CALL BDOS POP H ! POP D ! POP B PUSH PSW ; SAVE CHAR CALL CRLF1 POP PSW ; RESTORE CHAR RET * * PRINT CHAR IN A ON CON: * CHAR$OUT: PUSH PSW ! PUSH B ! PUSH D ! PUSH H MVI C,2 ; WRITE MOV E,A ; CHAR IN E CALL BDOS POP H ! POP D ! POP B ! POP PSW RET * * PRINT ERROR MSG PTED TO BY DE; ENDS IN '$' * PRINT$MESSAGE: PUSH B ! PUSH D ! PUSH H MVI C,9 ; PRINT BUFFER CALL BDOS POP H ! POP D ! POP B RET * * MOVE BYTES PTED TO BY HL TO AREA PTED TO BY DE; B BYTES TO MOVE * MOVE: MOV A,M ; GET BYTE ANI 7FH ; MASK OFF MSB -- IN CASE A WS FILE STAX D ; PUT BYTE INX H ; PT TO NEXT INX D DCR B ; COUNT DOWN JNZ MOVE RET * * READ RECORD FROM DISK; NEXT$ADR CONTAINS ADDRESS TO READ TO * ON RETURN, BDOS ERROR CODE IS IN A (0=NO ERROR) * READ$RECORD: MVI C,20 ; READ NEXT RECORD LXI D,FCB ; PT TO FCB CALL BDOS PUSH PSW ; SAVE RETURN CODE LHLD NEXT$ADR ; PT TO LOAD ADDRESS LXI D,BUFF ; PT TO BUFFER TO LOAD FROM MVI B,128 ; NUMBER OF BYTES TO MOVE XCHG CALL MOVE XCHG SHLD NEXT$ADR ; PT TO NEXT LOAD ADDRESS POP PSW ; GET RETURN CODE RET * * PRINT ONE LINE OF INFO SECTION; HL PTS TO LINE UPON ENTRY; * HL PTS TO FIRST CHAR OF NEXT LINE UPON EXIT * PRINT$LINE: MOV A,M ; GET CHAR CPI CR ; EOL? JZ CRLF CPI LF ; LINE FEED? (WS FILE) JZ CRLF0 CALL CHAR$OUT ; PRINT CHAR INX H ; PT TO NEXT JMP PRINT$LINE * * PRINT CRLF, PT TO FIRST CHAR OF NEXT LINE, AND PAGE IF NECESSARY * CRLF: INX H ; PT TO LF CRLF0: INX H ; PT TO 1ST CHAR OF NEXT LINE CRLFC: CALL CRLF1 ; PRINT CRLF LDA LINE$CNT ; GET LINE COUNT DCR A STA LINE$CNT RNZ ; OK -- CONTINUE LXI D,PAGEMS CALL PRINT$MESSAGE ; PRINT PAGE MESSAGE CALL CHAR$IN ; GET RESPONSE ANI 0DFH ; CAPITALIZE CPI 'A' ; ABORT? JZ HELP ; START OVER IF SO CPI CTRLC ; CP/M ABORT JZ HELP$EXIT CALL SET$LINE$CNT CALL CRLF1 ; NEW LINE RET * * PRINT CR AND LF ONLY * CRLF1: MVI A,CR ; PRINT CR CALL CHAR$OUT MVI A,LF ; PRINT LF CALL CHAR$OUT RET * * SET LINE$CNT VARIABLE TO SCREEN SIZE * SET$LINE$CNT: MVI A,LINES$PER$SCREEN-1 STA LINE$CNT RET * * PRINT THE HEADER SECTION AND LOAD FIRST$ENTRY PTR * PRINT$HEADER: LXI H,HELP$BUF CALL SET$LINE$CNT MVI A,'A' ; INIT SELECTION CHAR STA SEL$CHAR LXI D,SELECTMS CALL PRINT$MESSAGE MVI C,0 ; COUNT NUMBER OF SELECTIONS * PRINT LINE UNTIL FIRST INFORMATION SECTION FOUND PH1: MOV A,M ; GET CHAR CPI SECT$CHAR JZ PH2 CPI CTRLZ ; EOF? -- ABORT JZ HELP$EXIT INR C ; INCREMENT SELECTION COUNT LDA SEL$CHAR ; DISPLAY SELECTION CHAR CALL CHAR$OUT INR A ; INCR CHAR STA SEL$CHAR MVI A,'.' CALL CHAR$OUT MVI A,' ' CALL CHAR$OUT CALL PRINT$LINE ; PRINT HEADER LINE JMP PH1 * SAVE PTR TO FIRST ENTRY PH2: SHLD FIRST$ENTRY RET * * PRINT AN INFORMATION SECTION * PRINT$INFO: CALL SET$LINE$CNT PI1: CALL PRINT$LINE ; PRINT LINE FROM INFO FILE MOV A,M ; DONE? CPI CTRLZ ; EOF? JZ PI2 CPI SECT$CHAR ; NEXT SECTION JZ PI2 CPI FF ; FORM FEED? JNZ PI1 CALL FORM$FEED ; FEED SCREEN JMP PI1 * FORM FEED SCREEN FORM$FEED: LDA LINE$CNT ; GET LINE COUNT MOV B,A ; ... IN B FEED$LOOP: PUSH B ; SAVE B CALL CRLFC ; NEW LINE POP B ; GET B DCR B ; COUNT DOWN JNZ FEED$LOOP RET * END OF INFO PI2: CALL CRLF1 ; NEW LINE LDA LINE$CNT ; COUNT DOWN DCR A STA LINE$CNT JNZ PI2 LXI D,ENDMS ; PRINT END OF INFORMATION MSG CALL PRINT$MESSAGE CALL CHAR$IN ; GET ANY CHAR CPI CTRLC ; CP/M ABORT JZ HELP$EXIT CALL SET$LINE$CNT ; RESET LINE COUNT IN CASE OF ALL RET ********************************************************* * MESSAGE AND BUFFER SECTION * ********************************************************* HELPMS: DB 'HELP V1.1',CR,LF,'$' ENDMS: DB ' ++ EOI ++' DB ' Type CTRL-C to return to CP/M, to continue -$' SELECTMS: DB CR,LF,' HELP File Selections are --',CR,LF,'$' DEFFN: DB 0,'HELP ' DEFEXT: DB 'HLP' PAGEMS: DB ' Type "A"=Abort, CTRL-C=CP/M, =Cont -$' ERR1: DB CR,LF,'HELP FATAL ERROR -- File not Found$' ERR2: DB CR,LF,'HELP ERROR -- Invalid Response',CR,LF,'$' ERR3: DB CR,LF,'HELP ERROR -- EOF on HELP File',CR,LF,'$' PROMPT$MESSAGE: DB CR,LF,' Type CTRL-C to return to CP/M, "*" to select' DB ' all, or enter selection - $' SEL$CHAR: DS 1 ; SELECTION TABLE OPTION CHAR FIRST$ENTRY: DS 2 ; PTR TO FIRST ENTRY OF INFORMATION SECTION LINE$CNT: DS 1 ; LINE COUNT BUFFER DFFLG: DS 1 ; DEFAULT FILE FLAG (0=NOT SEARCH FOR, 1=YES) NEXT$ADR: DS 2 ; NEXT LOAD ADDRESS DS 80 ; STACK SPACE STACK: DS 2 ; CP/M STACK PTR * * DEFAULT HELP MESSAGE * HELP$BUF: DB ':The HELP Subsystem for Online Documentation' DB CR,LF,' This is HELP, the Online Documentation Subsystem.' DB CR,LF,'The purpose of HELP is to allow the user to ' DB 'interactively' DB CR,LF,'query the *.HLP files of the system in order to receive' DB CR,LF,'information summaries on various aspects of the user''s' DB CR,LF,'working environment, such as the language systems he is' DB CR,LF,'using and certain subsystems available to him.' DB CR,LF,LF,' When the user types ''HELP'', a search is done' DB CR,LF,'for the file ''HELP.HLP''. If found, the contents of' DB CR,LF,'this HELP File is displayed to the user; if not found,' DB CR,LF,'the HELP Information you are now reading is displayed.' DB CR,LF,LF,' If the user desires information on a specific' DB CR,LF,'topic and he has a HELP File of that name (ie, CPM.HLP' DB CR,LF,'is a HELP File on CP/M), he may issue of HELP Command' DB CR,LF,'of the form --' DB CR,LF,' HELP d:topic' DB CR,LF,'where "d:" is the disk the HELP File resides on' DB ' (optional)' DB CR,LF,'and "topic" is the name of the HELP File (topic.HLP,' DB CR,LF,'like CPM.HLP).' DB CR,LF,' Please refer to the HELP File "HELP.HLP" for' DB ' more information.' DB CR,LF,CTRLZ ; END OF FILE END