home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Oakland CPM Archive
/
oakcpm.iso
/
sigm
/
sigmv013.ark
/
HELP.ASM
< prev
next >
Wrap
Assembly Source File
|
1984-04-29
|
13KB
|
536 lines
* 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 <FILENAME>.<EXT> *
* *
* <FILENAME>.<EXT> IS OPTIONAL; IF OMITTED COMPLETELY, *
* 'HELP.HLP' IS ASSUMED; IF JUST <EXT> 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 ; <CR>
LF EQU 0AH ; <LF>
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 ; <CTRL-Z>?
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 ; <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, <CR> 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, <CR>=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