home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol099 / help2.asm < prev    next >
Assembly Source File  |  1984-04-29  |  31KB  |  1,489 lines

  1. *
  2. *  PROGRAM NAME:  HELP2
  3. *  AUTHOR:  RICHARD CONN
  4. *  DATE:  14 JAN 83
  5. *  VERSION:  4.0
  6. *  PREVIOUS VERSIONS:  3.2 (6 JAN 83)
  7. *  PREVIOUS VERSIONS:  3.1 (8 DEC 82), 3.0 (11 OCT 82), 2.0 (30 OCT 81)
  8. *  PREVIOUS VERSIONS:  1.8 (18 OCT 81), 1.7 (10 SEP 81), 1.6 (9 SEP 81)
  9. *  PREVIOUS VERSIONS:  1.5 (9 SEP 81), 1.4 (8 SEP 81), 1.3 (8 SEP 81)
  10. *  PREVIOUS VERSIONS:  1.2 (7 SEP 81), 1.1 (6 OCT 80), 1.0 (18 NOV 79)
  11. *  NOTE:  FOR USE WITH ZCPR 2.0 AND LATER
  12. *
  13. VERS    EQU    40
  14.  
  15. ;
  16. ;    This program is Copyright (c) 1982, 1983 by Richard Conn
  17. ;    All Rights Reserved
  18. ;
  19. ;    ZCPR2 and its utilities, including this one, are released
  20. ; to the public domain.  Anyone who wishes to USE them may do so with
  21. ; no strings attached.  The author assumes no responsibility or
  22. ; liability for the use of ZCPR2 and its utilities.
  23. ;
  24. ;    The author, Richard Conn, has sole rights to this program.
  25. ; ZCPR2 and its utilities may not be sold without the express,
  26. ; written permission of the author.
  27. ;
  28.  
  29. ;
  30. ;    HELP supports an online documentation system under ZCPR2.  Refer
  31. ; to the file HELP.HLP for more details.
  32. ;
  33.  
  34. ;
  35. ;  CP/M Constants
  36. ;
  37. FALSE        EQU    0
  38. TRUE        EQU    NOT FALSE
  39.  
  40. UDFLAG        EQU    4    ; ADDRESS OF USER/DISK FLAG
  41. BDOS        EQU    5    ; ADDRESS OF BDOS ENTRY POINT
  42. FCB        EQU    5CH    ; ADDRESS OF FILE CONTROL BLOCK
  43. BUFF        EQU    80H    ; ADDRESS OF DMA BUFFER
  44.  
  45. CR        EQU    0DH    ; <CR>
  46. LF        EQU    0AH    ; <LF>
  47. FF        EQU    'L'-40H    ; CTRL-L = FORM FEED
  48. CTRLZ        EQU    'Z'-40H    ; CTRL-Z
  49. CTRLC        EQU    'C'-40H    ; CTRL-C
  50.  
  51. ;
  52. ;  HELP Control Characters
  53. ;
  54. SECT$CHAR    EQU    ':'    ; DEFINED TO BE COLON
  55. BACKUP$CHAR    EQU    'L'    ; BACK UP TO PREVIOUS FRAME CHAR
  56. START$CHAR    EQU    'S'    ; JUMP TO START OF INFORMATION CHAR
  57. MENU$CHAR    EQU    'M'    ; CHAR TO ABORT TO MENU
  58. CPM$ABORT$CHAR    EQU    CTRLC    ; CHAR TO ABORT TO CP/M
  59. LEVEL$RET$CHAR    EQU    '^'    ; RETURN TO PREVIOUS HELP LEVEL
  60. ROOT$CHAR    EQU    '.'    ; RETURN TO ROOT OF HELP
  61.  
  62. ;
  63. ;  Lines/Screen on CRT
  64. ;
  65. LINES$PER$SCREEN    EQU    24    ; ASSUME 24 LINES/SCREEN
  66.  
  67. ;
  68. ;  Number of File Names per Line
  69. ;
  70. NAMES$PER$LINE        EQU    6    ; 6 NAMES (SPACE = 6*11 COLS)
  71.  
  72. ;
  73. ;  Set this to TRUE if all files must be of type HLP
  74. ;
  75. FORCE$HLP        EQU    TRUE     ; TRUE IF FILES MUST BE OF TYPE HLP
  76.  
  77. ;
  78. ;  Number of Nodes (Levels) in Help File Tree
  79. ;
  80. HELP$MAX        EQU    10    ; DEFAULT = 10 (SPACE=11*HELP$MAX)
  81.  
  82.  
  83. ;
  84. ; MACROS TO PROVIDE Z80 EXTENSIONS
  85. ;   MACROS INCLUDE:
  86. ;
  87. $-MACRO         ;FIRST TURN OFF THE EXPANSIONS
  88. ;
  89. ;    JR    - JUMP RELATIVE
  90. ;    JRC    - JUMP RELATIVE IF CARRY
  91. ;    JRNC    - JUMP RELATIVE IF NO CARRY
  92. ;    JRZ    - JUMP RELATIVE IF ZERO
  93. ;    JRNZ    - JUMP RELATIVE IF NO ZERO
  94. ;    DJNZ    - DECREMENT B AND JUMP RELATIVE IF NO ZERO
  95. ;    LDIR    - MOV @HL TO @DE FOR COUNT IN BC
  96. ;    LXXD    - LOAD DOUBLE REG DIRECT
  97. ;    SXXD    - STORE DOUBLE REG DIRECT
  98. ;
  99. ;
  100. ;
  101. ;    @GENDD MACRO USED FOR CHECKING AND GENERATING
  102. ;    8-BIT JUMP RELATIVE DISPLACEMENTS
  103. ;
  104. @GENDD    MACRO    ?DD    ;;USED FOR CHECKING RANGE OF 8-BIT DISPLACEMENTS
  105.     IF (?DD GT 7FH) AND (?DD LT 0FF80H)
  106.     DB    100H    ;Displacement Range Error on Jump Relative
  107.     ELSE
  108.     DB    ?DD
  109.     ENDIF
  110.     ENDM
  111. ;
  112. ;
  113. ; Z80 MACRO EXTENSIONS
  114. ;
  115. JR    MACRO    ?N    ;;JUMP RELATIVE
  116.     DB    18H
  117.     @GENDD    ?N-$-1
  118.     ENDM
  119. ;
  120. JRC    MACRO    ?N    ;;JUMP RELATIVE ON CARRY
  121.     DB    38H
  122.     @GENDD    ?N-$-1
  123.     ENDM
  124. ;
  125. JRNC    MACRO    ?N    ;;JUMP RELATIVE ON NO CARRY
  126.     DB    30H
  127.     @GENDD    ?N-$-1
  128.     ENDM
  129. ;
  130. JRZ    MACRO    ?N    ;;JUMP RELATIVE ON ZERO
  131.     DB    28H
  132.     @GENDD    ?N-$-1
  133.     ENDM
  134. ;
  135. JRNZ    MACRO    ?N    ;;JUMP RELATIVE ON NO ZERO
  136.     DB    20H
  137.     @GENDD    ?N-$-1
  138.     ENDM
  139. ;
  140. DJNZ    MACRO    ?N    ;;DECREMENT B AND JUMP RELATIVE ON NO ZERO
  141.     DB    10H
  142.     @GENDD    ?N-$-1
  143.     ENDM
  144. ;
  145. LDIR    MACRO        ;;LDIR
  146.     DB    0EDH,0B0H
  147.     ENDM
  148. ;
  149. LDED    MACRO    ?N    ;;LOAD DE DIRECT
  150.     DB    0EDH,05BH
  151.     DW    ?N
  152.     ENDM
  153. ;
  154. LBCD    MACRO    ?N    ;;LOAD BC DIRECT
  155.     DB    0EDH,4BH
  156.     DW    ?N
  157.     ENDM
  158. ;
  159. SDED    MACRO    ?N    ;;STORE DE DIRECT
  160.     DB    0EDH,53H
  161.     DW    ?N
  162.     ENDM
  163. ;
  164. SBCD    MACRO    ?N    ;;STORE BC DIRECT
  165.     DB    0EDH,43H
  166.     DW    ?N
  167.     ENDM
  168. ;
  169. ; END OF Z80 MACRO EXTENSIONS
  170. ;
  171.  
  172.     ORG    100H
  173.  
  174. ;
  175. ;  Branch to Start of Program
  176. ;
  177.     jmp    start
  178.  
  179. ;
  180. ;******************************************************************
  181. ;
  182. ;  SINSFORM -- ZCPR2 Utility Standard General Purpose Initialization Format
  183. ;
  184. ;    This data block precisely defines the data format for
  185. ; initial features of a ZCPR2 system which are required for proper
  186. ; initialization of the ZCPR2-Specific Routines in SYSLIB.
  187. ;
  188.  
  189. ;
  190. ;  EXTERNAL PATH DATA
  191. ;
  192. EPAVAIL:
  193.     DB    0FFH    ; IS EXTERNAL PATH AVAILABLE? (0=NO, 0FFH=YES)
  194. EPADR:
  195.     DW    40H    ; ADDRESS OF EXTERNAL PATH IF AVAILABLE
  196.  
  197. ;
  198. ;  INTERNAL PATH DATA
  199. ;
  200. INTPATH:
  201.     DB    0,0    ; DISK, USER FOR FIRST PATH ELEMENT
  202.             ; DISK = 1 FOR A, '$' FOR CURRENT
  203.             ; USER = NUMBER, '$' FOR CURRENT
  204.     DB    0,0
  205.     DB    0,0
  206.     DB    0,0
  207.     DB    0,0
  208.     DB    0,0
  209.     DB    0,0
  210.     DB    0,0    ; DISK, USER FOR 8TH PATH ELEMENT
  211.     DB    0    ; END OF PATH
  212.  
  213. ;
  214. ;  MULTIPLE COMMAND LINE BUFFER DATA
  215. ;
  216. MCAVAIL:
  217.     DB    0FFH    ; IS MULTIPLE COMMAND LINE BUFFER AVAILABLE?
  218. MCADR:
  219.     DW    0FF00H    ; ADDRESS OF MULTIPLE COMMAND LINE BUFFER IF AVAILABLE
  220.  
  221. ;
  222. ;  DISK/USER LIMITS
  223. ;
  224. MDISK:
  225.     DB    4    ; MAXIMUM NUMBER OF DISKS
  226. MUSER:
  227.     DB    31    ; MAXIMUM USER NUMBER
  228.  
  229. ;
  230. ;  FLAGS TO PERMIT LOG IN FOR DIFFERENT USER AREA OR DISK
  231. ;
  232. DOK:
  233.     DB    0FFH    ; ALLOW DISK CHANGE? (0=NO, 0FFH=YES)
  234. UOK:
  235.     DB    0FFH    ; ALLOW USER CHANGE? (0=NO, 0FFH=YES)
  236.  
  237. ;
  238. ;  PRIVILEGED USER DATA
  239. ;
  240. PUSER:
  241.     DB    10    ; BEGINNING OF PRIVILEGED USER AREAS
  242. PPASS:
  243.     DB    'chdir',0    ; PASSWORD FOR MOVING INTO PRIV USER AREAS
  244.     DS    41-($-PPASS)    ; 40 CHARS MAX IN BUFFER + 1 for ending NULL
  245.  
  246. ;
  247. ;  CURRENT USER/DISK INDICATOR
  248. ;
  249. CINDIC:
  250.     DB    '$'    ; USUAL VALUE (FOR PATH EXPRESSIONS)
  251.  
  252. ;
  253. ;  DMA ADDRESS FOR DISK TRANSFERS
  254. ;
  255. DMADR:
  256.     DW    80H    ; TBUFF AREA
  257.  
  258. ;
  259. ;  NAMED DIRECTORY INFORMATION
  260. ;
  261. NDRADR:
  262.     DW    00000H    ; ADDRESS OF MEMORY-RESIDENT NAMED DIRECTORY
  263. NDNAMES:
  264.     DB    64    ; MAX NUMBER OF DIRECTORY NAMES
  265. DNFILE:
  266.     DB    'NAMES   '    ; NAME OF DISK NAME FILE
  267.     DB    'DIR'        ; TYPE OF DISK NAME FILE
  268.  
  269. ;
  270. ;  REQUIREMENTS FLAGS
  271. ;
  272. EPREQD:
  273.     DB    0FFH    ; EXTERNAL PATH?
  274. MCREQD:
  275.     DB    000H    ; MULTIPLE COMMAND LINE?
  276. MXREQD:
  277.     DB    000H    ; MAX USER/DISK?
  278. UDREQD:
  279.     DB    000H    ; ALLOW USER/DISK CHANGE?
  280. PUREQD:
  281.     DB    000H    ; PRIVILEGED USER?
  282. CDREQD:
  283.     DB    000H    ; CURRENT INDIC AND DMA?
  284. NDREQD:
  285.     DB    000H    ; NAMED DIRECTORIES?
  286. Z2CLASS:
  287.     DB    5    ; CLASS 5
  288.     DB    'ZCPR2'
  289.     DS    10    ; RESERVED
  290.  
  291. ;
  292. ;  END OF SINSFORM -- STANDARD DEFAULT PARAMETER DATA
  293. ;
  294. ;******************************************************************
  295. ;
  296.  
  297. ;
  298. ;  DEFAULT FILE NAME
  299. ;
  300. DEFFN:
  301.     DB    'HELP    '
  302. DEFTYP:
  303.     DB    'HLP'
  304.  
  305. ;
  306. ;  Start of Program
  307. ;
  308. START:
  309.     LXI    H,0    ; GET SP
  310.     DAD    SP
  311.     SHLD    STACK
  312.     LXI    SP,STACK    ; NEW STACK
  313.     MVI    E,0FFH        ; GET CURRENT USER NUMBER
  314.     MVI    C,32
  315.     CALL    BDOS
  316.     STA    CUR$USER    ; CURRENT USER NUMBER
  317.     LDA    BDOS+2    ; BASE PAGE OF BDOS
  318.     SUI    10    ; 2K + 2 PAGES
  319.     STA    TPA$END
  320.     XRA    A    ; A=0
  321.     STA    DFFLG    ; TURN OFF DEFAULT FILE FLAG
  322.     STA    HELP$LEVEL    ; SET HELP LEVEL TO 0 (NO RETURN FILE)
  323.     LXI    D,HELPMS    ; PRINT OPENING MSG
  324.     CALL    PRINT$MESSAGE
  325.     LXI    H,FCB+1    ; CHECK FOR FILE NAME
  326.     MOV    A,M
  327.     CPI    ' '    ; NONE?
  328.     JRNZ    START1
  329.  
  330. *  INSERT 'HELP.HLP' INTO FCB OR CLEAR FCB
  331.     LXI    D,DEFFN    ; PT TO DEFAULT NAME
  332.     MVI    B,11    ; 11 BYTES
  333.     XCHG
  334.     CALL    MOVE    ; MOVE (HL) TO (DE) FOR (B) BYTES
  335.     MVI    A,1    ; TURN ON DEFAULT FILE FLAG
  336.     STA    DFFLG
  337.  
  338. *  START/RESTART HELP PROGRAM (START ON INITIAL ENTRY, RESTART ON NODE LOAD)
  339. START1:
  340.     LXI    SP,STACK    ; SET STACK POINTER
  341.  
  342. *  CLEAR NON-NAME/TYPE BYTES IN FCB
  343.     LXI    H,FCB    ; INITIAL ZERO
  344.     MVI    M,0    ; STORE 0 FOR DRIVE (CURRENT LOGGED-IN)
  345.     LXI    D,12    ; SKIP TO EXTENT
  346.     DAD    D
  347.     MVI    B,24    ; FILL 24 BYTES
  348. FCB$FILL:
  349.     MVI    M,0    ; ZERO FILL
  350.     INX    H    ; PT TO NEXT
  351.     DJNZ    FCB$FILL
  352.  
  353. *  CHECK FOR WILD CARDS IN FILE NAME -- ERROR IF SO
  354.     LXI    H,FCB+1    ; PT TO FIRST BYTE OF FILE NAME
  355.     MVI    B,11    ; 11 BYTES
  356. FCB$WILD$CK:
  357.     MOV    A,M    ; GET BYTE
  358.     ANI    7FH    ; MASK
  359.     CPI    '?'    ; WILD?
  360.     JRZ    FCB$WILD$ERROR
  361.     INX    H    ; PT TO NEXT
  362.     DJNZ    FCB$WILD$CK
  363.  
  364. *  CHECK FOR FILE TYPE
  365.     LXI    H,FCB+9    ; CHECK FOR FILE TYPE
  366.  
  367.     IF    NOT FORCE$HLP    ; IF FILE TYPE MAY NOT BE HLP
  368.     MOV    A,M    ; CHECK FOR FILE TYPE SPECIFIED
  369.     CPI    ' '    ; NONE?
  370.     JRNZ    START2
  371.     ENDIF
  372.  
  373. *  PLACE DEFAULT FILE TYPE OF '.HLP' IN FCB
  374. DEFAULT$EXT:
  375.     LXI    D,DEFTYP    ; DEFAULT FILE TYPE
  376.     MVI    B,3
  377.     XCHG
  378.     CALL    MOVE    ; MOVE (HL) TO (DE) FOR (B) BYTES
  379.  
  380. *  OPEN FILE
  381. START2:
  382.     LDA    DFFLG    ; CHECK FOR DEFAULT
  383.     ORA    A    ; 0=NO
  384.     JNZ    HELP$DEF    ; DISPLAY DEFAULT HELP INFO WITH FILE NAMES
  385.     LXI    H,INTPATH    ; SET BASE ADDRESS OF PATH
  386.     LDA    EPAVAIL        ; EXTERNAL PATH AVAILABLE
  387.     ORA    A        ; 0=NO
  388.     JRZ    START2A
  389.     LHLD    EPADR        ; GET ADDRESS OF EXTERNAL PATH
  390. START2A:
  391.     LXI    D,FCB        ; PT TO FCB
  392.     CALL    FNDFILE        ; SEARCH FOR FILE
  393.     JNZ    START3        ; FILE FOUND, SO PROCESS
  394.     LDA    EPAVAIL        ; SEARCH ALONG EXTERNAL PATH?
  395.     ORA    A        ; 0=NO
  396.     JRZ    START2B
  397.     LXI    H,INTPATH    ; SELECT INTERNAL PATH THEN
  398.     LXI    D,FCB        ; PT TO FCB
  399.     CALL    FNDFILE        ; SEARCH
  400.     JNZ    START3        ; FILE FOUND
  401.  
  402. *  FILE NOT FOUND -- FATAL ERROR
  403. START2B:
  404.     LXI    D,ERR1    ; FILE NOT FOUND
  405.     CALL    PRINT$MESSAGE
  406.     JMP    HELP$EXIT
  407.  
  408. *  FILE CONTAINS WILD CARDS -- FATAL ERROR
  409. FCB$WILD$ERROR:
  410.     LXI    D,WILD$ERR    ; WILD CARD
  411.     CALL    PRINT$MESSAGE
  412.     JMP    HELP$EXIT
  413.  
  414. *
  415. *  DISPLAY DEFAULT HELP FILE INFORMATION
  416. *
  417. HELP$DEF:
  418.     LXI    D,HELP$DEF$MSG    ; PRINT MESSAGE
  419.     CALL    PRINT$MESSAGE
  420.     CALL    SET$COUNT    ; SET COUNTER
  421.     CALL    RESET$SYSTEM    ; RETURN HOME
  422.     CALL    PRINT$HELP$FILES    ; PRINT HELP FILES AT HOME
  423.     LDA    EPAVAIL        ; EXTERNAL PATH?
  424.     LHLD    EPADR        ; EXTERNAL PATH ADDRESS
  425.     ORA    A        ; 0=NO EXTERNAL PATH
  426.     CNZ    HDFF1
  427.     CALL    RESET$SYSTEM    ; RETURN HOME
  428.     LXI    H,INTPATH    ; FOLLOW INTERNAL PATH
  429.     CALL    HDFF1        ; SEARCH IT
  430.     CALL    RESET$SYSTEM    ; RESET CALLING DISK/USER NUMBER
  431.     LXI    D,HELP$EDEF$MSG    ; PRINT END MESSAGE
  432.     CALL    PRINT$MESSAGE
  433.     CALL    CHAR$IN        ; GET ANY CHAR FOR RESPONSE
  434.     CPI    CTRLC        ; ABORT?
  435.     JZ    HELP$EXIT
  436.     XRA    A        ; TURN OFF DEFAULT
  437.     STA    DFFLG
  438.     LXI    H,DEFFN        ; SET DEFAULT FILE NAME
  439.     LXI    D,FCB+1
  440.     MVI    B,11        ; 11 BYTES
  441.     CALL    MOVE
  442.     JMP    START2        ; PROCESS DEFAULT HELP FILE
  443.  
  444. ;
  445. ; MAIN SEARCH LOOP
  446. ;
  447. HDFF1:
  448.     LDA    CINDIC        ;GET CURRENT DISK INDICATOR
  449.     MOV    B,A        ;... IN B
  450.     MOV    A,M        ;GET DRIVE
  451.     ANI    7FH        ;MASK MSB
  452.     ORA    A        ;0=DONE=COMMAND NOT FOUND
  453.     RZ            ;END OF PATH?
  454. ;
  455. ; LOOK FOR COMMAND IN DIRECTORY PTED TO BY HL; DRIVE IN A
  456. ;
  457.     CMP    B
  458.     JRNZ    HDFF2        ;SKIP DEFAULT DRIVE SELECTION IF SO
  459.     LDA    UDFLAG        ;GET DEFAULT USER/DISK
  460.     ANI    0FH        ;MASK FOR DEFAULT DISK
  461.     INR    A        ;PREP FOR FOLLOWING DCR A
  462. HDFF2:
  463.     DCR    A        ;ADJUST PATH 1 TO 0 FOR A, ETC
  464.     MOV    E,A        ;DISK NUMBER IN E
  465.     MVI    C,14        ;SELECT DISK FCT
  466.     CALL    BENTRY        ;SELECT DRIVE
  467.     INX    H        ;PT TO USER NUMBER
  468.     MOV    A,M        ;GET USER NUMBER
  469.     INX    H        ;PT TO NEXT PATH ELEMENT
  470.     ANI    7FH        ;MASK OUT MSB
  471.     CMP    B
  472.     JRNZ    HDFF3        ;DO NOT SELECT CURRENT USER IF SO
  473.     LDA    CUR$USER    ;GET ORIGINAL USER NUMBER
  474. HDFF3:
  475.     MOV    E,A        ;SELECT USER
  476.     MVI    C,32
  477.     CALL    BENTRY
  478.     PUSH    H        ;SAVE PATH PTR
  479.     CALL    PRINT$HELP$FILES
  480.     POP    H        ;GET PATH PTR
  481.     JR    HDFF1
  482.  
  483. *
  484. *  SET FILE NAME COUNTER
  485. *
  486. SET$COUNT:
  487.     MVI    A,NAMES$PER$LINE    ; NUMBER OF FILE NAMES/LINE
  488.     STA    NAME$COUNT
  489.     RET
  490.  
  491. *
  492. *  PRINT NAMES OF HELP FILES
  493. *
  494. PRINT$HELP$FILES:
  495.     LXI    H,FCB        ; MAKE FCB = *.HLP
  496.     MVI    M,0        ; BEGINNING 0 FOR DEFAULT DISK
  497.     MVI    B,8        ; FILL 8 ?'S
  498.     INX    H        ; PT TO FIRST CHAR
  499. PHF1:
  500.     MVI    M,'?'        ; '?' FILL
  501.     INX    H        ; PT TO NEXT
  502.     DJNZ    PHF1
  503.     LXI    D,DEFTYP    ; COPY DEFAULT FILE TYPE
  504.     MVI    B,3        ; 3 BYTES
  505.     XCHG            ; EXCHANGE
  506.     CALL    MOVE        ; COPY
  507.     XCHG            ; RESTORE PTR
  508.     MVI    B,24        ; FILL REST WITH 0'S
  509. PHF2:
  510.     MVI    M,0        ; 0 FILL
  511.     INX    H        ; PT TO NEXT
  512.     DJNZ    PHF2
  513.  
  514. *  SEARCH FOR FIRST FILE
  515.     LXI    D,FCB        ; PT TO FCB
  516.     MVI    C,17        ; SEARCH FOR FIRST
  517.     CALL    BDOS
  518.     CPI    0FFH        ; NONE?
  519.     RZ            ; DONE IF SO
  520.  
  521. *  PRINT CURRENT AND SEARCH FOR NEXT
  522. PHF3:
  523.     CALL    PRINT$HFN    ; PRINT HELP FILE NAME
  524.     LXI    D,FCB        ; PT TO FCB
  525.     MVI    C,18        ; SEARCH FOR NEXT
  526.     CALL    BDOS
  527.     CPI    0FFH        ; DONE?
  528.     JRNZ    PHF3
  529.     RET
  530.  
  531. *
  532. *  PRINT NAME OF FILE WHOSE BUFF OFFSET IS IN A
  533. *
  534. PRINT$HFN:
  535.     RRC            ; A=A*32
  536.     RRC
  537.     RRC            ; RATHER THAN 5 LEFT, I DO 3 RIGHT (NEAT, HUH?)
  538.     ANI    60H        ; MASK ALL BUT INTERESTING PART
  539.     LXI    H,BUFF        ; PT TO BUFFER
  540.     ADD    L        ; PT TO ENTRY
  541.     MOV    L,A
  542.     MOV    A,H
  543.     ACI    0
  544.     MOV    H,A        ; HL PTS TO ENTRY
  545.     INX    H        ; HL PTS TO HELP FILE NAME
  546.     MVI    B,8        ; 8 CHARS
  547. PHFN1:
  548.     MOV    A,M        ; GET CHAR
  549.     ANI    7FH        ; MASK
  550.     INX    H        ; PT TO NEXT
  551.     CALL    CHAR$OUT    ; PRINT IT
  552.     DJNZ    PHFN1
  553.     MVI    A,' '        ; TRAILING SPACES
  554.     CALL    CHAR$OUT    ; 3 OF THEM
  555.     CALL    CHAR$OUT
  556.     CALL    CHAR$OUT
  557.     LDA    NAME$COUNT    ; COUNT DOWN
  558.     DCR    A
  559.     STA    NAME$COUNT
  560.     RNZ
  561.     CALL    SET$COUNT    ; RESET COUNT
  562.     CALL    CRLF        ; NEW LINE
  563.     RET
  564.  
  565. *
  566. *  LOAD HELP FILE INFORMATION
  567. *
  568. START3:
  569.     LXI    D,FCB        ; OPEN FILE
  570.     MVI    C,15        ; BDOS FILE OPEN
  571.     CALL    BDOS
  572.     LXI    H,HELP$BUF    ; PT TO BUFFER
  573.     SHLD    NEXT$ADR    ; SET PTR
  574.  
  575. *  READ RECORDS UNTIL EOF
  576. START4:
  577.     CALL    READ$RECORD    ; READ INFO
  578.     JRZ    START4    ; NOT DONE IF ZERO RETURN
  579.     LXI    D,FCB    ; CLOSE FILE
  580.     MVI    C,16    ; CLOSE
  581.     CALL    BDOS
  582.     CALL    RESET$SYSTEM    ; RESTORE CURRENT DISK AND USER IF CHANGED
  583.  
  584. *
  585. *  START OF HELP PROGRAM
  586. *
  587. HELP:
  588.     LXI    SP,STACK    ; RESET STACK
  589.     MVI    A,0    ; SET NO FRAME
  590.     STA    FRAME$NUMBER
  591.     LXI    H,HELP$BUF    ; PT TO BUFFER
  592.     MOV    A,M    ; NO HEADER SECTION?
  593.     ANI    7FH    ; MASK OUT MSB
  594.     CPI    SECT$CHAR
  595.     JRNZ    HELP1    ; HEADER SECTION EXISTS
  596.     CALL    PRINT$INFO    ; PRINT HELP INFO PTED TO BY HL
  597.     LDA    HELP$LEVEL    ; CHECK TO SEE IF WE ARE NOT AT LEVEL 0
  598.     ORA    A    ; 0=LEVEL 0
  599.     JRZ    HELP$EXIT    ; ABORT IF SO
  600.     JMP    LEVEL$RETURN    ; GO TO PREVIOUS LEVEL IF NOT
  601.  
  602. *  EXIT POINT FOR ANY EXIT FROM THE REST OF THE HELP PROGRAM
  603. HELP$EXIT:
  604.     CALL    RESET$SYSTEM    ; RESET CALLING DISK/USER NUMBER
  605.     LHLD    STACK    ; GET CP/M SP
  606.     SPHL
  607.     RET        ; DONE
  608.  
  609. *  PRINT HEADER INFORMATION AND SELECT AN OPTION
  610. HELP1:
  611.     CALL    PRINT$HEADER    ; PRINT HEADER
  612.     PUSH    B    ; SAVE C (NUMBER OF VALID SELECTIONS)
  613.     CALL    CRLF1    ; NEW LINE
  614.     CALL    PR$LEVEL    ; PRINT LEVEL NUMBER
  615.     LXI    D,PROMPT1$MESSAGE    ; PRINT PROMPT
  616.     CALL    PRINT$MESSAGE
  617.     LXI    D,PROMPT2$MESSAGE    ; LEVEL COMMAND
  618.     LDA    HELP$LEVEL    ; CURRENT LEVEL = 0?
  619.     ORA    A    ; SET FLAGS
  620.     JRZ    HELP1A
  621.     CALL    PRINT$MESSAGE
  622. HELP1A:
  623.     LXI    D,PROMPT3$MESSAGE
  624.     CALL    PRINT$MESSAGE
  625.     POP    B    ; GET C
  626.     CALL    CHAR$IN        ; GET RESPONSE
  627.     CPI    CTRLC        ; RETURN TO CP/M
  628.     JRZ    HELP$EXIT
  629.     CPI    ROOT$CHAR    ; GO TO ROOT
  630.     JZ    GO$ROOT
  631.     CPI    LEVEL$RET$CHAR    ; RETURN TO PREVIOUS LEVEL
  632.     JZ    LEVEL$RETURN
  633.     PUSH    PSW    ; SAVE CHAR
  634.     CALL    CRLF1
  635.     POP    PSW    ; GET CHAR
  636.     SUI    'A'-1        ; ADJUST FOR COUNT
  637.     MOV    B,A        ; SAVE COUNT
  638.     JRZ    BAD$RESPONSE
  639.     JRNC    HELP2
  640.  
  641. *  INVALID RESPONSE
  642. BAD$RESPONSE:
  643.     LXI    D,ERR2    ; INVALID RESPONSE
  644.     CALL    PRINT$MESSAGE
  645.     JR    HELP1
  646.  
  647. *  VALID RESPONSE -- LOOK FOR AND PRINT INFORMATION SECTION
  648. HELP2:
  649.     INR    C    ; 1 MORE THAN NUMBER OF POSSIBLE SELECTIONS
  650.     CMP    C    ; GREATER THAN NUMBER OF POSSIBLE SELECTIONS?
  651.     JRNC    BAD$RESPONSE
  652.     LHLD    FIRST$ENTRY    ; GET PTR TO FIRST ENTRY
  653.  
  654. *  PRINT INFORMATION WHEN COUNT IS ZERO
  655. HELP3:
  656.     DJNZ    HELP4
  657.     CALL    PRINT$INFO    ; PRINT INFO PTED TO BY HL
  658.     JR    HELP1
  659.  
  660. *  LOCATE NEXT INFORMATION SECTION
  661. HELP4:
  662.     MOV    A,M    ; <CTRL-Z>?
  663.     ANI    7FH    ; MASK OUT MSB
  664.     INX    H    ; PT TO NEXT BYTE
  665.     CPI    CTRLZ
  666.     JZ    HELP$ERR    ; HELP FILE FORMAT ERROR
  667.     CPI    LF    ; LINE FEED (WS FILE)?
  668.     JRZ    HELP5
  669.     CPI    CR    ; <CR>?
  670.     JRNZ    HELP4
  671.     INX    H    ; 1ST BYTE OF NEXT LINE
  672. HELP5:
  673.     MOV    A,M    ; GET CHAR
  674.     ANI    7FH    ; MASK OUT MSB
  675.     CPI    SECT$CHAR    ; NEW SECTION?
  676.     JRZ    HELP3    ; CONTINUE LOOP IF SO
  677.     CPI    CTRLZ    ; EOF?
  678.     JRNZ    HELP4    ; CONTINUE IF NOT
  679.  
  680. *  ERROR -- REACHED END OF HELP FILE
  681. HELP$ERR:
  682.     LXI    D,ERR3    ; FORMAT ERROR
  683.     CALL    PRINT$MESSAGE
  684.     JMP    HELP1
  685.  
  686.  
  687. *********************************************************
  688. *                            *
  689. *  HELP SUPPORT ROUTINE SECTION                *
  690. *                            *
  691. *********************************************************
  692.  
  693. *
  694. *  RESTORE CURRENT DISK AND CURRENT USER
  695. *
  696. RESET$SYSTEM:
  697.     LDA    UDFLAG    ; GET DISK
  698.     ANI    0FH    ; GET DISK NUMBER
  699.     MOV    E,A    ; DISK IN E
  700.     MVI    C,14    ; SELECT DISK
  701.     CALL    BDOS
  702.     LDA    CUR$USER    ; SET USER
  703.     MOV    E,A    ; USER IN E
  704.     MVI    C,32    ; SET USER CODE
  705.     CALL    BDOS
  706.     RET
  707.  
  708. *
  709. *  FNDFILE -- LOOK FOR FILE ALONG ZCPR2 PATH
  710. *  INPUT PARAMETERS:  HL = BASE ADDRESS OF PATH, DE = PTR TO FCB OF FILE
  711. *  OUTPUT PARAMETERS:  A=0 AND ZERO FLAG SET IF NOT FOUND, NZ IF FOUND
  712. *
  713. FNDFILE:
  714.     SHLD    PATH        ;SAVE PATH BASE ADDRESS
  715.     MVI    C,17        ;SEARCH FOR FIRST
  716.     CALL    BENTRY        ;LOOK FOR FILE
  717.     INR    A        ;SET FLAG
  718.     JRNZ    FF5        ;FOUND IT -- RETURN FOUND FLAG
  719.     XCHG            ;HL=FCB PTR
  720.     SHLD    FCBPTR        ;SAVE IT
  721.     LHLD    PATH        ;PT TO PATH FOR FAILURE POSSIBILITY
  722. ;
  723. ; MAIN SEARCH LOOP
  724. ;
  725. FF1:
  726.     LDA    CINDIC        ;GET CURRENT USER/DISK INDICATOR
  727.     MOV    B,A        ;... IN B
  728.     MOV    A,M        ;GET DRIVE
  729.     ANI    7FH        ;MASK MSB
  730.     ORA    A        ;0=DONE=COMMAND NOT FOUND
  731.     JRNZ    FF2        ;NO ERROR ABORT?
  732. ;
  733. ; FILE NOT FOUND ERROR
  734. ;
  735.     XRA    A        ;ZERO FLAG MEANS NOT FOUND
  736.     RET
  737. ;
  738. ; LOOK FOR COMMAND IN DIRECTORY PTED TO BY HL; DRIVE IN A
  739. ;
  740. FF2:
  741.     CMP    B        ;CURRENT DISK?
  742.     JRNZ    FF3        ;SKIP DEFAULT DRIVE SELECTION IF SO
  743.     LDA    UDFLAG        ;GET DEFAULT USER/DISK
  744.     ANI    0FH        ;MASK FOR DEFAULT DISK
  745.     INR    A        ;PREP FOR FOLLOWING DCR A
  746. FF3:
  747.     DCR    A        ;ADJUST PATH 1 TO 0 FOR A, ETC
  748.     MOV    E,A        ;DISK NUMBER IN E
  749.     MVI    C,14        ;SELECT DISK FCT
  750.     CALL    BENTRY        ;SELECT DRIVE
  751.     INX    H        ;PT TO USER NUMBER
  752.     MOV    A,M        ;GET USER NUMBER
  753.     ANI    7FH        ;MASK OUT MSB
  754.     INX    H        ;PT TO NEXT ENTRY IN PATH
  755.     CMP    B        ;CURRENT USER?
  756.     JRNZ    FF4        ;DO NOT SELECT CURRENT USER IF SO
  757.     LDA    CUR$USER    ;GET ORIGINAL USER NUMBER
  758. FF4:
  759.     MOV    E,A        ;SELECT USER
  760.     MVI    C,32
  761.     CALL    BENTRY
  762.     XCHG            ;SAVE PTR TO NEXT PATH ELEMENT IN DE
  763.     LHLD    FCBPTR        ;GET PTR TO FCB
  764.     XCHG            ;... IN DE, PATH PTR IN HL
  765.     MVI    C,17        ;SEARCH FOR FIRST
  766.     CALL    BENTRY        ;LOOK FOR FILE
  767.     INR    A        ;SET FLAG
  768.     JRZ    FF1        ;CONTINUE PATH SEARCH IF SEARCH FAILED
  769. ;
  770. ; FILE FOUND -- PERFORM SYSTEM TEST AND PROCEED IF APPROVED
  771. ;
  772. FF5:
  773.     MVI    A,0FFH        ;SET OK RETURN
  774.     ORA    A
  775.     RET
  776.  
  777. ;
  778. ;  BDOS ROUTINE
  779. ;
  780. BENTRY:
  781.     PUSH    H    ;SAVE REGS
  782.     PUSH    D
  783.     PUSH    B
  784.     CALL    BDOS
  785.     POP    B    ;GET REGS
  786.     POP    D
  787.     POP    H
  788.     RET
  789.  
  790. * BUFFERS
  791. FCBPTR:
  792.     DS    2    ;POINTER TO FCB FOR FILE SEARCH
  793. PATH:
  794.     DS    2    ;BASE ADDRESS OF PATH
  795.  
  796. *
  797. *  INPUT CHAR; CHAR IS IN A
  798. *
  799. CHAR$IN:
  800.     PUSH B ! PUSH D ! PUSH H
  801.     MVI    C,1    ; READ CHAR
  802.     CALL    BDOS
  803.     POP H ! POP D ! POP B
  804.     PUSH    PSW    ; SAVE CHAR
  805.     CALL    CRLF1
  806.     POP    PSW    ; RESTORE CHAR
  807. *
  808. *  CAPITALIZE CHAR IN A
  809. *
  810. CAPS:
  811.     ANI    7FH    ; MASK OUT MSB
  812.     CPI    61H    ; LESS THAN SMALL A?
  813.     RC
  814.     CPI    7BH    ; LESS THAN LEFT BRACE?
  815.     RNC
  816.     ANI    5FH    ; CAPITALIZE
  817.     RET
  818.  
  819. *
  820. *  PRINT CHAR IN A ON CON:
  821. *
  822. CHAR$OUT:
  823.     PUSH PSW ! PUSH B ! PUSH D ! PUSH H
  824.     MVI    C,2    ; WRITE
  825.     MOV    E,A    ; CHAR IN E
  826.     CALL    BDOS
  827.     POP H ! POP D ! POP B ! POP PSW
  828.     RET
  829.  
  830. *
  831. *  PRINT ERROR MSG PTED TO BY DE; ENDS IN '$'
  832. *
  833. PRINT$MESSAGE:
  834.     PUSH B ! PUSH D ! PUSH H
  835.     MVI    C,9    ; PRINT BUFFER
  836.     CALL    BDOS
  837.     POP H ! POP D ! POP B
  838.     RET
  839.  
  840. *
  841. *  MOVE BYTES PTED TO BY HL TO AREA PTED TO BY DE; B BYTES TO MOVE
  842. *
  843. MOVE:
  844.     MOV    A,M    ; GET BYTE
  845.     ANI    7FH    ; MASK OFF MSB -- IN CASE A WS FILE
  846.     STAX    D    ; PUT BYTE
  847.     INX    H    ; PT TO NEXT
  848.     INX    D
  849.     DJNZ    MOVE
  850.     RET
  851.  
  852. *
  853. *  READ RECORD FROM DISK; NEXT$ADR CONTAINS ADDRESS TO READ TO
  854. *    ON RETURN, BDOS ERROR CODE IS IN A (0=NO ERROR)
  855. *
  856. READ$RECORD:
  857.     MVI    C,20    ; READ NEXT RECORD
  858.     LXI    D,FCB    ; PT TO FCB
  859.     CALL    BDOS
  860.     PUSH    PSW    ; SAVE RETURN CODE
  861.     LHLD    NEXT$ADR    ; PT TO LOAD ADDRESS
  862.     LDA    TPA$END    ; CHECK AGAINST END PAGE OF TPA
  863.     CMP    H    ; IF AT SAME PAGE, YES
  864.     JZ    READ$ERROR
  865.     LXI    D,BUFF    ; PT TO BUFFER TO LOAD FROM
  866.     MVI    B,128    ; NUMBER OF BYTES TO MOVE
  867.     XCHG
  868.     CALL    MOVE
  869.     XCHG
  870.     MVI    M,CTRLZ    ; STORE ENDING CTRLZ IN CASE OF EOF
  871.     POP    PSW    ; GET RETURN CODE
  872.     ORA    A    ; DONE?  <>0 IF SO
  873.  
  874. *  READ DONE -- SAVE PTR TO NEXT BLOCK
  875.     SHLD    NEXT$ADR    ; SET NEXT ADDRESS
  876.     RET
  877.  
  878. READ$ERROR:
  879.     LXI    D,READERR
  880.     CALL    PRINT$MESSAGE
  881.     JMP    HELP$EXIT
  882.  
  883. *
  884. *  PRINT ONE LINE OF INFO SECTION; HL PTS TO LINE UPON ENTRY;
  885. *    HL PTS TO FIRST CHAR OF NEXT LINE UPON EXIT
  886. *
  887. PRINT$LINE:
  888.     MOV    A,M    ; GET CHAR
  889.     ANI    7FH    ; MASK OUT MSB
  890.     CPI    CR    ; EOL?
  891.     JRZ    CRLF
  892.     CPI    LF    ; LINE FEED? (WS FILE)
  893.     JRZ    CRLF0
  894.     CPI    CTRLZ    ; END OF FILE?
  895.     JRZ    CRLFC    ; DONE IF SO
  896.     CALL    CHAR$OUT    ; PRINT CHAR
  897.     INX    H    ; PT TO NEXT
  898.     JR    PRINT$LINE
  899.  
  900. *
  901. *  PRINT CRLF, PT TO FIRST CHAR OF NEXT LINE, AND PAGE IF NECESSARY
  902. *
  903. CRLF:
  904.     INX    H    ; PT TO LF
  905. CRLF0:
  906.     INX    H    ; PT TO 1ST CHAR OF NEXT LINE
  907. CRLFC:
  908.     CALL    CRLF1    ; PRINT CRLF
  909.     LDA    LINE$CNT    ; GET LINE COUNT
  910.     DCR    A
  911.     STA    LINE$CNT
  912.     RNZ        ; OK -- CONTINUE
  913.     MOV    A,M    ; SET MSB OF FIRST CHAR OF NEXT LINE
  914.     ORI    80H
  915.     MOV    M,A    ; MSB IS SET FOR LATER BACKUP
  916. FRAME$PAUSE:
  917.     CALL    PR$LEVEL    ; PRINT LEVEL NUMBER
  918.     LDA    FRAME$NUMBER    ; INCREMENT FRAME NUMBER
  919.     INR    A
  920.     STA    FRAME$NUMBER
  921.     LXI    D,PAGEMS
  922.     CALL    PRINT$MESSAGE    ; PRINT PAGE MESSAGE
  923.     LXI    D,PAGE1MS    ; NOT LEVEL 0?
  924.     LDA    HELP$LEVEL    ; GET LEVEL NUMBER
  925.     ORA    A    ; SET FLAGS
  926.     JRZ    FP1
  927.     CALL    PRINT$MESSAGE
  928. FP1:
  929.     LXI    D,PAGE2MS
  930.     CALL    PRINT$MESSAGE
  931.     CALL    CHAR$IN    ; GET RESPONSE
  932.     CPI    MENU$CHAR    ; ABORT?
  933.     JZ    HELP    ; START OVER IF SO
  934.     CPI    CPM$ABORT$CHAR    ; CP/M ABORT
  935.     JZ    HELP$EXIT
  936.     CPI    ROOT$CHAR    ; GO TO ROOT
  937.     JZ    GO$ROOT
  938.     CPI    LEVEL$RET$CHAR    ; RETURN TO HIGHER LEVEL
  939.     JZ    LEVEL$RETURN
  940.     CPI    BACKUP$CHAR    ; BACK UP?
  941.     JZ    FRAME$BACKUP
  942.     CPI    START$CHAR    ; JUMP TO START OF INFO
  943.     JZ    INFO$START
  944. FRAME$RESUME:
  945.     SHLD    START$OF$FRAME
  946.     CALL    SET$LINE$CNT
  947.     CALL    CRLF1    ; NEW LINE
  948.     RET
  949.  
  950. *  JUMP TO START OF INFORMATION
  951. INFO$START:
  952.     LHLD    START$OF$INFO    ; PT TO START OF INFO
  953.     MVI    A,1        ; RESET FRAME COUNT
  954.     STA    FRAME$NUMBER
  955.     JMP    FRAME$RESUME    ; CONTINUE PROCESSING
  956.  
  957. *  BACK UP TO PREVIOUS FRAME
  958. FRAME$BACKUP:
  959.     CALL    BOI$CHECK    ; AT BEGINNING OF INFORMATION?
  960.     JRNZ    FB1        ; CONTINUE IF NOT
  961.     JMP    FRAME$PAUSE
  962. FB1:
  963.     DCX    H    ; BACK UP UNTIL BYTE WITH MSB SET IS FOUND
  964.     MOV    A,M    ; GET BYTE
  965.     ANI    80H
  966.     JRZ    FB1
  967.     LDA    FRAME$NUMBER    ; DECREMENT FRAME NUMBER
  968.     DCR    A        ; BACK UP TO CURRENT FRAME NUMBER
  969.     DCR    A        ; BACK UP TO PREVIOUS FRAME NUMBER
  970.     STA    FRAME$NUMBER
  971.     JMP    FRAME$RESUME    ; CONTINUE PROCESSING
  972. *
  973. *  PRINT CR AND LF ONLY
  974. *
  975. CRLF1:
  976.     MVI    A,CR    ; PRINT CR
  977.     CALL    CHAR$OUT
  978.     MVI    A,LF    ; PRINT LF
  979.     JMP    CHAR$OUT
  980.  
  981. *
  982. *  SET LINE$CNT VARIABLE TO SCREEN SIZE
  983. *
  984. SET$LINE$CNT:
  985.     MVI    A,LINES$PER$SCREEN-1
  986.     STA    LINE$CNT
  987.     RET
  988.  
  989. *
  990. *  PRINT THE HEADER SECTION AND LOAD FIRST$ENTRY PTR
  991. *    ON RETURN, C=NUMBER OF POSSIBLE SELECTIONS
  992. *
  993. PRINT$HEADER:
  994.     MVI    A,0    ; SET NO FRAME
  995.     STA    FRAME$NUMBER
  996.     LXI    H,HELP$BUF
  997.     CALL    SET$LINE$CNT
  998.     MVI    A,'A'    ; INIT SELECTION CHAR
  999.     STA    SEL$CHAR
  1000.     LXI    D,SELECTMS
  1001.     CALL    PRINT$MESSAGE
  1002.     MVI    C,0    ; COUNT NUMBER OF SELECTIONS
  1003.  
  1004. * PRINT LINE UNTIL FIRST INFORMATION SECTION FOUND
  1005. PH1:
  1006.     MOV    A,M    ; GET CHAR
  1007.     ANI    7FH    ; MASK OUT MSB
  1008.     CPI    SECT$CHAR
  1009.     JRZ    PH2
  1010.     CPI    CTRLZ    ; EOF? -- ABORT
  1011.     JZ    HELP$EXIT
  1012.     INR    C    ; INCREMENT SELECTION COUNT
  1013.     LDA    SEL$CHAR    ; DISPLAY SELECTION CHAR
  1014.     CALL    CHAR$OUT
  1015.     INR    A    ; INCR CHAR
  1016.     STA    SEL$CHAR
  1017.     MVI    A,'.'
  1018.     CALL    CHAR$OUT
  1019.     MVI    A,' '
  1020.     CALL    CHAR$OUT
  1021.     CALL    PRINT$LINE    ; PRINT HEADER LINE
  1022.     JR    PH1
  1023.  
  1024. *  SAVE PTR TO FIRST ENTRY
  1025. PH2:
  1026.     SHLD    FIRST$ENTRY
  1027.     RET
  1028.  
  1029. *
  1030. *  PRINT AN INFORMATION SECTION
  1031. *    INFORMATION SECTION IS PTED TO BY HL
  1032. *
  1033. PRINT$INFO:
  1034.     SHLD    START$OF$INFO    ; SET START OF INFORMATION POINTER
  1035.     CALL    LOAD$NODE    ; LOAD NEW NODE IF DUAL SECT$CHAR
  1036.     SHLD    START$OF$FRAME    ; SET FRAME POINTER
  1037.     MOV    A,M    ; SET MSB
  1038.     ORI    80H
  1039.     MOV    M,A
  1040.     CALL    SET$LINE$CNT
  1041.     MVI    A,1        ; A=1
  1042.     STA    FRAME$NUMBER    ; SET FRAME NUMBER
  1043. PI1:
  1044.     CALL    PRINT$LINE    ; PRINT LINE FROM INFO FILE
  1045.     MOV    A,M    ; DONE?
  1046.     ANI    7FH    ; MASK OUT MSB
  1047.     CPI    CTRLZ    ; EOF?
  1048.     JRZ    PI2
  1049.     CPI    SECT$CHAR    ; NEXT SECTION
  1050.     JRZ    PI2
  1051.     CPI    FF    ; FORM FEED?
  1052.     JRNZ    PI1
  1053.     INX    H    ; PT TO CHAR AFTER FORM FEED
  1054.     CALL    FORM$FEED    ; FEED SCREEN
  1055.     JR    PI1
  1056.  
  1057. *  FORM FEED SCREEN
  1058. FORM$FEED:
  1059.     LDA    LINE$CNT    ; GET LINE COUNT
  1060.     MOV    B,A    ; ... IN B
  1061. FEED$LOOP:
  1062.     PUSH    B    ; SAVE B
  1063.     CALL    CRLFC    ; NEW LINE
  1064.     POP    B    ; GET B
  1065.     DJNZ    FEED$LOOP
  1066.     RET
  1067.  
  1068. *  END OF INFO
  1069. PI2:
  1070.     MOV    A,M    ; SET MSB OF NEXT BYTE
  1071.     ORI    80H
  1072.     MOV    M,A
  1073. PI2A:
  1074.     CALL    CRLF1    ; NEW LINE
  1075.     LDA    LINE$CNT    ; COUNT DOWN
  1076.     DCR    A
  1077.     STA    LINE$CNT
  1078.     JRNZ    PI2A
  1079. PI2$MSG:
  1080.     CALL    PR$LEVEL    ; PRINT LEVEL NUMBER
  1081.     LDA    FRAME$NUMBER    ; INCREMENT FRAME NUMBER
  1082.     INR    A
  1083.     STA    FRAME$NUMBER
  1084.     LXI    D,ENDMS        ; PRINT END OF INFORMATION MSG
  1085.     CALL    PRINT$MESSAGE
  1086.     LXI    D,PAGE1MS    ; PRINT LEVEL UP MESSAGE OPTIONALLY
  1087.     LDA    HELP$LEVEL    ; GET CURRENT HELP LEVEL
  1088.     ORA    A    ; SET FLAGS
  1089.     JRZ    PI2$MSG1
  1090.     CALL    PRINT$MESSAGE
  1091. PI2$MSG1:
  1092.     LXI    D,PAGE2MS    ; PRINT REST OF INFO MESSAGE
  1093.     CALL    PRINT$MESSAGE
  1094.     CALL    CHAR$IN    ; GET ANY CHAR
  1095.     CPI    MENU$CHAR    ; MENU ABORT
  1096.     JZ    HELP
  1097.     CPI    CPM$ABORT$CHAR    ; CP/M ABORT
  1098.     JZ    HELP$EXIT
  1099.     CPI    ROOT$CHAR    ; GO TO ROOT
  1100.     JZ    GO$ROOT
  1101.     CPI    LEVEL$RET$CHAR    ; RETURN TO HIGHER LEVEL
  1102.     JZ    LEVEL$RETURN
  1103.     CPI    BACKUP$CHAR    ; BACK UP FROM EOI?
  1104.     JZ    PI2$BACKUP
  1105.     CPI    START$CHAR    ; START OF INFO?
  1106.     JZ    PI2$START
  1107.     JMP    SET$LINE$CNT    ; RESET LINE COUNT IN CASE OF ALL
  1108.  
  1109. *  JUMP TO START OF INFO
  1110. PI2$START:
  1111.     LHLD    START$OF$INFO    ; PT TO START OF INFO
  1112.     CALL    FRAME$RESUME    ; RESET POINTERS
  1113.     MVI    A,1        ; RESET FRAME COUNT
  1114.     STA    FRAME$NUMBER
  1115.     JMP    PI1    ; CONTINUE PROCESSING
  1116.  
  1117. *  BACK UP TO PREVIOUS FRAME
  1118. PI2$BACKUP:
  1119.     CALL    BOI$CHECK    ; AT BEGINNING OF INFORMATION?
  1120.     JZ    PI2$MSG
  1121. PI2$BACK:
  1122.     CALL    FB1    ; BACK UP TO PREVIOUS FRAME
  1123.     JMP    PI1    ; CONTINUE PROCESSING
  1124.  
  1125. *
  1126. *  CHECK FOR POSITION AT BEGINNING OF INFORMATION SECTION
  1127. *    IF SO, PRINT BACKUP ERROR MESSAGE AND RETURN W/ZERO SET
  1128. *
  1129. BOI$CHECK:
  1130.     LHLD    START$OF$INFO    ; START ADDRESS
  1131.     XCHG            ; ... IN DE
  1132.     LHLD    START$OF$FRAME    ; FRAME ADDRESS
  1133.     MOV    A,D        ; EQUAL?
  1134.     CMP    H
  1135.     RNZ
  1136.     MOV    A,E
  1137.     CMP    L
  1138.     RNZ
  1139.     LXI    D,BACKERR    ; BACKUP ERROR
  1140.     CALL    PRINT$MESSAGE
  1141.     XRA    A        ; ZERO FLAG SET
  1142.     STA    FRAME$NUMBER    ; SET FRAME NUMBER
  1143.     RET
  1144.  
  1145. *
  1146. *  AT THE BEGINNING OF AN INFORMATION SECTION (HL PTS TO FIRST CHAR)
  1147. *    CHECK TO SEE IF ANOTHER SECT$CHAR FOLLOWS, AND, IF SO, LOAD THE
  1148. *    SPECIFIED FILE AS A NEW NODE AND BEGIN PROCESSING IT
  1149. *
  1150. LOAD$NODE:
  1151.     INX    H    ; PT TO POSSIBLE 2ND SECT$CHAR
  1152.     MOV    A,M    ; GET IT
  1153.     DCX    H    ; PREP FOR RETURN
  1154.     ANI    7FH    ; MASK MSB
  1155.     CPI    SECT$CHAR    ; ANOTHER ONE?
  1156.     RNZ        ; PROCESS NORMALLY IF NOT
  1157.  
  1158. *  WE HAVE A NEW NODE -- CHECK TO SEE IF WE CAN NEST AGAIN
  1159.     LDA    HELP$LEVEL    ; GET CURRENT HELP LEVEL
  1160.     CPI    HELP$MAX    ; AT MAXIMUM?
  1161.     JRNZ    LOAD$NODE1
  1162.     LXI    D,LEVELERR    ; LEVEL ERROR MESSAGE
  1163.     CALL    PRINT$MESSAGE
  1164.     JMP    HELP$EXIT
  1165.  
  1166. *  WE HAVE NOT REACHED LEVEL LIMIT, SO CONTINUE
  1167. *  AT THIS TIME, A=HELP LEVEL INDEX AND HL = PTR TO CURRENT SECTION (::)
  1168. LOAD$NODE1:
  1169.  
  1170. *  SAVE CURRENT HELP FILE NAME FOR RETURN
  1171.     INX    H    ; PT TO SECTION SECT$CHAR
  1172.     INX    H    ; NOW POINTING TO FILE NAME
  1173.     PUSH    H    ; SAVE PTR
  1174.     CALL    COMP$HELP$NAME$PTR    ; HL=POINTER TO STACK ELT INDEXED BY A
  1175.     XCHG        ; DE=ADDRESS OF NEXT ELEMENT
  1176.  
  1177. *  COPY CURRENT NODE ELEMENT NAME INTO NEXT STACK ELEMENT
  1178.     LXI    H,FCB+1    ; PT TO FILE NAME
  1179.     MVI    B,11    ; 11 BYTES
  1180.     CALL    MOVE
  1181.  
  1182. *  INCREMENT HELP LEVEL
  1183.     LDA    HELP$LEVEL    ; GET OLD LEVEL
  1184.     INR    A    ; SET NEW LEVEL
  1185.     STA    HELP$LEVEL
  1186.  
  1187. *  SET UP FCB FOR NEW FILE
  1188.     LXI    D,LOADING$MSG
  1189.     CALL    PRINT$MESSAGE
  1190.     POP    H    ; GET PTR TO NEW FILE NAME
  1191.     LXI    D,FCB+1    ; PT TO FCB NAME
  1192.     MVI    B,8    ; 8 CHARS MAX
  1193.     CALL    LOAD$FCB    ; PLACE INTO FCB WITH ERROR CHECKING
  1194.     MVI    A,'.'    ; DECIMAL BETWEEN FILE NAME AND TYPE
  1195.     CALL    CHAR$OUT
  1196.     MVI    B,3    ; 3 CHARS MAX FOR TYPE
  1197.     CALL    LOAD$FCB    ; PLACE INTO FCB WITH ERROR CHECKING
  1198.     CALL    CRLF1    ; NEW LINE
  1199.     JMP    START1    ; LOAD NEW HELP FILE
  1200.  
  1201. *
  1202. *  LOAD FCB PTED TO BY DE WITH "NORMAL" FILE NAME PTED TO BY HL FOR B BYTES
  1203. *
  1204. LOAD$FCB:
  1205.     MOV    A,M    ; GET CHAR
  1206.     INX    H    ; PT TO NEXT
  1207.     CPI    '.'    ; DONE IF DECIMAL
  1208.     JRZ    LOAD$FCB$FILL
  1209.     CPI    ' '+1    ; DONE IF < <SP>
  1210.     JRC    LOAD$FCB$FILL
  1211.     CALL    CAPS    ; CAPITALIZE
  1212.     CALL    CHAR$OUT    ; PRINT FILE NAME AND TYPE
  1213.     STAX    D    ; STORE CHAR
  1214.     INX    D    ; PT TO NEXT
  1215.     DJNZ    LOAD$FCB
  1216.     MOV    A,M    ; CHECK FOR ERROR
  1217.     ANI    7FH    ; MASK MSB
  1218.     INX    H    ; PT TO NEXT CHAR
  1219.     CPI    '.'    ; OK IF '.'
  1220.     RZ
  1221.     CPI    ' '+1    ; OK IF <SP>
  1222.     RC
  1223.     LXI    D,LOADERR
  1224.     CALL    PRINT$MESSAGE
  1225.     JMP    HELP$EXIT
  1226. LOAD$FCB$FILL:
  1227.     MOV    C,A    ; SAVE CHAR THAT TERMINATED STRING
  1228. LOAD$FCB$LOOP:
  1229.     MVI    A,' '    ; <SP> FILL REST OF FCB
  1230.     STAX    D    ; STORE <SP>
  1231.     INX    D    ; PT TO NEXT
  1232.     DJNZ    LOAD$FCB$LOOP
  1233.     MOV    A,C    ; GET CHAR THAT TERMINATED STRING
  1234.     RET
  1235.  
  1236. *
  1237. *  GO TO ROOT
  1238. *
  1239. GO$ROOT:
  1240.     LDA    HELP$LEVEL    ; AT ROOT?
  1241.     ORA    A    ; 0=YES
  1242.     JZ    HELP    ; RETURN TO HELP
  1243.     MVI    A,0    ; SET ROOT INDEX
  1244.     JR    GORET
  1245.  
  1246. *
  1247. *  RETURN TO PREVIOUS HELP LEVEL
  1248. *
  1249. LEVEL$RETURN:
  1250.     LDA    HELP$LEVEL    ; ARE WE AT THE LOWEST LEVEL?
  1251.     ORA    A    ; 0=YES
  1252.     JRNZ    LRET
  1253.     LXI    D,LRETERR
  1254.     CALL    PRINT$MESSAGE
  1255.     JMP    HELP
  1256.  
  1257. *  SET NEW HELP LEVEL
  1258. LRET:
  1259.     DCR    A    ; DOWN 1
  1260.  
  1261. *  GO TO HELP LEVEL INDEXED IN A
  1262. GORET:
  1263.     STA    HELP$LEVEL    ; SET NEW HELP LEVEL
  1264.     CALL    COMP$HELP$NAME$PTR    ; HL=POINTER TO TARGET HELP FILE NAME
  1265.     PUSH    H    ; SAVE PTR TO FILE NAME
  1266.     LXI    D,LOADING$MSG    ; PRINT NAME OF FILE TO BE LOADED
  1267.     CALL    PRINT$MESSAGE
  1268.     MVI    B,8    ; 8 CHARS TO FILE NAME
  1269. GORET$NAME:
  1270.     MOV    A,M    ; GET CHAR
  1271.     CPI    ' '    ; END OF NAME?
  1272.     INX    H    ; PT TO NEXT
  1273.     JRZ    GORET$NAME0
  1274.     CALL    CHAR$OUT    ; PRINT FILE NAME
  1275.     DJNZ    GORET$NAME
  1276.     JMP    GORET$NAME1
  1277. GORET$NAME0:
  1278.     DCR    B    ; COUNT DOWN
  1279.     JRZ    GORET$NAME1
  1280.     INX    H    ; SKIP NEXT SPACE
  1281.     JR    GORET$NAME0
  1282. GORET$NAME1:
  1283.     MVI    A,'.'    ; PRINT DECIMAL
  1284.     CALL    CHAR$OUT
  1285.     MVI    B,3    ; PRINT FILE TYPE
  1286. GORET$NAME2:
  1287.     MOV    A,M    ; GET CHAR
  1288.     INX    H    ; PT TO NEXT
  1289.     CALL    CHAR$OUT    ; PRINT IT
  1290.     DJNZ    GORET$NAME2
  1291.     CALL    CRLF1    ; NEW LINE
  1292.     POP    H    ; GET PTR TO FILE NAME
  1293.     LXI    D,FCB+1    ; COPY ELEMENT INTO FCB
  1294.     MVI    B,11    ; 11 BYTES
  1295.     CALL    MOVE
  1296.     JMP    START1    ; LOAD ENTRY
  1297.  
  1298. *
  1299. *  COMPUTE POINTER TO HELP NAME ENTRY INDEXED BY HELP LEVEL IN A
  1300. *
  1301. COMP$HELP$NAME$PTR:
  1302.     CALL    COMP$OFFSET    ; COMPUTE OFFSET IN TABLE
  1303.     LXI    D,HELP$NAME$STACK    ; PT TO BASE OF HELP NAMES
  1304.     DAD    D    ; ADD IN OFFSET
  1305.     RET
  1306.  
  1307. *
  1308. *  COMPUTE OFFSET INTO TABLE BASED ON INDEX A
  1309. *    OFFSET = A * 11
  1310. *
  1311. COMP$OFFSET:
  1312.     MOV    L,A    ; VALUE IN HL
  1313.     MVI    H,0
  1314.     MOV    E,L    ; DE=HL
  1315.     MOV    D,H
  1316.  
  1317.     DAD    H    ; *2
  1318.     DAD    H    ; *4
  1319.     DAD    H    ; *8
  1320.     DAD    D    ; *9
  1321.     DAD    D    ; *10
  1322.     DAD    D    ; *11
  1323.     RET
  1324.  
  1325. *
  1326. *  PRINT LEVEL NUMBER
  1327. *
  1328. PR$LEVEL:
  1329.     LDA    HELP$LEVEL    ; DON'T PRINT LEVEL 0
  1330.     ORA    A    ; 0?
  1331.     JRZ    PR$FRAME
  1332.     LXI    D,LEVEL$MESSAGE    ; PRINT HEADER
  1333.     CALL    PRINT$MESSAGE
  1334.     LDA    HELP$LEVEL    ; GET NUMBER
  1335.     CALL    PR$DEC        ; PRINT AS DECIMAL
  1336.     LXI    D,LEVEL2$MESSAGE    ; PRINT END HEADER
  1337.     CALL    PRINT$MESSAGE
  1338. PR$FRAME:
  1339.     LDA    FRAME$NUMBER    ; GET CURRENT FRAME NUMBER
  1340.     ORA    A    ; SET FLAGS
  1341.     RZ        ; NO FRAME?
  1342.     CALL    PR$DEC    ; PRINT AS DECIMAL
  1343.     LXI    D,LEVEL3$MESSAGE
  1344.     CALL    PRINT$MESSAGE
  1345.     RET
  1346. *  PRINT A AS DECIMAL
  1347. PR$DEC:
  1348.     PUSH    PSW    ; SAVE VALUE
  1349.     XRA    A
  1350.     STA    LD$SPACE
  1351.     POP    PSW    ; GET VALUE
  1352.     MVI    B,100    ; PRINT 100'S
  1353.     CALL    PDEC
  1354.     MVI    B,10    ; PRINT 10'S
  1355.     CALL    PDEC
  1356.     ADI    '0'    ; PRINT 1'S
  1357.     JMP    CHAR$OUT
  1358. PDEC:
  1359.     MVI    C,0    ; SET VALUE
  1360. PDEC1:
  1361.     SUB    B    ; SUBTRACT POWER
  1362.     JRC    PDEC2
  1363.     INR    C    ; INCREMENT VALUE
  1364.     JR    PDEC1
  1365. PDEC2:
  1366.     ADD    B    ; ADD POWER BACK IN
  1367.     MOV    B,A    ; SAVE A IN B
  1368.     LDA    LD$SPACE    ; GET LEADING <SP> FLAG
  1369.     ORA    A    ; NON-ZERO=PRINT
  1370.     JRNZ    PDEC3
  1371.     MOV    A,C    ; GET DIGIT
  1372.     STA    LD$SPACE    ; NEW FLAG
  1373.     ORA    A    ; ZERO?
  1374.     JRNZ    PDEC3    ; PRINT BYTE IN C
  1375.     MVI    A,' '    ; PRINT LEADING SPACE
  1376.     JR    PDEC4
  1377. PDEC3:
  1378.     MOV    A,C    ; GET VALUE
  1379.     ADI    '0'    ; CONVERT TO ASCII
  1380. PDEC4:
  1381.     CALL    CHAR$OUT    ; PRINT CHAR
  1382.     MOV    A,B    ; RESTORE A
  1383.     RET
  1384.  
  1385. *********************************************************
  1386. *  MESSAGE AND BUFFER SECTION                *
  1387. *********************************************************
  1388.  
  1389. HELPMS:
  1390.     DB    'HELP for ZCPR2, Version '
  1391.     DB    (VERS/10)+'0','.',(VERS MOD 10)+'0',CR,LF,'$'
  1392. HELP$DEF$MSG:
  1393.     DB    CR,LF,'Default HELP Facility Invoked'
  1394.     DB    CR,LF,'    Available HELP Files are --',CR,LF,'$'
  1395. HELP$EDEF$MSG:
  1396.     DB    CR,LF,'    Type Any Character for Default Info (^C to Abort) - $'
  1397. SELECTMS:
  1398.     DB    CR,LF,'  HELP File Selections are --',CR,LF,'$'
  1399. ENDMS:
  1400.     DB    'EOI '
  1401. PAGEMS:
  1402.     DB    '^C=CP/M $'        ; ABORT TO CP/M CHAR
  1403. PAGE1MS:
  1404.     DB    LEVEL$RET$CHAR,'=Level '    ; RETURN TO HIGHER NODE
  1405.     DB    ROOT$CHAR,'=Root $'        ; RETURN TO ROOT
  1406. PAGE2MS:
  1407.     DB    MENU$CHAR,'=Menu '    ; ABORT TO MENU CHAR
  1408.     DB    START$CHAR,'=Start '    ; JUMP TO START OF INFORMATION CHAR
  1409.     DB    BACKUP$CHAR,'=Last '    ; BACK UP TO PREVIOUS FRAME CHAR
  1410.     DB    'CR=Next $'
  1411. WILD$ERR:
  1412.     DB    CR,LF,'HELP FATAL ERROR -- File Name Contains Wild Card$'
  1413. ERR1:
  1414.     DB    CR,LF,'HELP FATAL ERROR -- File not Found$'
  1415. ERR2:
  1416.     DB    CR,LF,'HELP ERROR -- Invalid Response',CR,LF,'$'
  1417. ERR3:
  1418.     DB    CR,LF,'HELP ERROR -- EOF on HELP File',CR,LF,'$'
  1419. BACKERR:
  1420.     DB    CR,LF,'HELP ERROR -- Not Possible to Backup Before Start of '
  1421.     DB    'Info',CR,LF,'$'
  1422. LEVELERR:
  1423.     DB    CR,LF,'HELP ERROR -- Node Level Limit Reached -- Aborting'
  1424.     DB    CR,LF,'$'
  1425. LOADERR:
  1426.     DB    CR,LF,'HELP ERROR -- Invalid File Name in Load',CR,LF,'$'
  1427. LRETERR:
  1428.     DB    CR,LF,'HELP ERROR -- No Higher Level to Return to',CR,LF,'$'
  1429. READERR:
  1430.     DB    CR,LF,'HELP ERROR -- Not Enough Room for HELP File',CR,LF,'$'
  1431. LEVEL$MESSAGE:
  1432.     DB    'Level $'
  1433. LEVEL2$MESSAGE:
  1434.     DB    '/ $'
  1435. LEVEL3$MESSAGE:
  1436.     DB    ': $'
  1437. PROMPT1$MESSAGE:
  1438.     DB    'Type  ^C=CP/M$'
  1439. PROMPT2$MESSAGE:
  1440.     DB    ' ',LEVEL$RET$CHAR,'=Level '
  1441.     DB    ROOT$CHAR,'=Root$'
  1442. PROMPT3$MESSAGE:
  1443.     DB    ' or Enter Selection $'
  1444. LOADING$MSG:
  1445.     DB    CR,LF,'Loading HELP File $'
  1446.  
  1447. CUR$USER:
  1448.     DS    1    ; NUMBER OF CURRENT USER
  1449. TPA$END:
  1450.     DS    1    ; END PAGE ADDRESS OF TPA
  1451. START$OF$INFO:
  1452.     DS    2    ; PTR TO START OF CURRENT INFORMATION BLOCK
  1453. START$OF$FRAME:
  1454.     DS    2    ; PTR TO START OF CURRENT FRAME
  1455. SEL$CHAR:
  1456.     DS    1    ; SELECTION TABLE OPTION CHAR
  1457. FIRST$ENTRY:
  1458.     DS    2    ; PTR TO FIRST ENTRY OF INFORMATION SECTION
  1459. LINE$CNT:
  1460.     DS    1    ; LINE COUNT BUFFER
  1461. NAME$COUNT:
  1462.     DS    1    ; COUNT OF FILE NAMES/LINE
  1463. DFFLG:
  1464.     DS    1    ; DEFAULT FILE FLAG (0=NOT SEARCH FOR, 1=YES)
  1465. NEXT$ADR:
  1466.     DS    2    ; NEXT LOAD ADDRESS
  1467. LD$SPACE:
  1468.     DS    1    ; LEADING SPACE FLAG FOR DECIMAL PRINT
  1469. HELP$LEVEL:
  1470.     DS    1    ; NUMBER OF HELP LEVEL CURRENT NODE IS AT (0=BOTTOM)
  1471. FRAME$NUMBER:
  1472.     DS    1    ; NUMBER OF CURRENT FRAME
  1473.  
  1474. HELP$NAME$STACK:
  1475.     DS    11*HELP$MAX    ; STACK OF HELP FILE NAMES OF EACH LEVEL
  1476.  
  1477.     DS    80    ; STACK SPACE
  1478. STACK:
  1479.     DS    2    ; CP/M STACK PTR
  1480.  
  1481. *
  1482. *  Help Files are Loaded Here
  1483. *
  1484. HELP$BUF    equ    $
  1485.  
  1486.     END
  1487.  
  1488.  
  1489.