home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / help / hbuild16.asm next >
Assembly Source File  |  1986-04-21  |  21KB  |  653 lines

  1. TITLE    HBUILD VERSION 1.60    16 December 1985
  2. Page    ,132
  3. COMMENT #
  4.                 HBUILD VERSION 1.60
  5.  
  6.     This is a universal help program engine that enables an    indexed
  7.     help program to be constructed from the HBUILD.COM file and a
  8.     suitably formatted text file.
  9.  
  10.     The text of the help file which is used as input to this program
  11.     must be formatted according to a set of exact criteria. It is
  12.     important that no errors be made in the layout, as, while I have
  13.     included some error trapping, it is not totally bulletproof.
  14.  
  15.     The first character to appear in the file is used by the program
  16.     as the separation character that it will look for in the rest of the
  17.     help file to indicate the end of a piece of text. This should be a
  18.     character that you will NOT use anywhere else in the help text.
  19.     I usually use the "happy face" (^A = ASCII 01) which my word processor
  20.     allows me to insert in a text file. The separation character must
  21.     appear as the first character in the help file followed immediately
  22.     by a CR and LF. The next character, again immediately followed by a
  23.     CR and LF is the exit character. This is the character which when
  24.     typed in response to any prompt and followed by a RETURN will exit
  25.     the program.
  26.  
  27.     The format of the help file is as follows (using @ as the separation
  28.     character and * as the exit character, so they will display easily on
  29.     your word processor) :
  30. @
  31. *
  32. MENU     
  33. User prompt for the first screen (placed on line 25)
  34. This will be the text of the first screen which will contain
  35. a list of help topics that can be requested. The data on this
  36. screen is for user information only. The program doesn't use
  37. anything here for index purposes. You may write any text here.
  38. Other screens can be used as sub-menu
  39. This is a list of commands:
  40.  
  41.         COMMAND 1
  42.         COMMAND 2
  43.         etc ...
  44.  
  45. @
  46. COMMAND 1
  47. User prompt that appears on COMMAND 1 topic screen on line 25
  48.             \70 COMMAND 1 TITLE IN REVERSE VIDEO \07
  49.  
  50. This is the help text for "COMMAND 1" which may be up to 24 lines of data
  51. starting at the line immediately follwing the 9 characters of "COMMAND 1".
  52. @
  53. COMMAND 2
  54. User prompt that appears on COMMAND 2 topic screen on line 25
  55.                 \01 COMMAND TWO \07
  56.  
  57. This is the help text for "COMMAND 2", whose title is this time shown as
  58. underlined on a monochrome screen, or in blue on a color screen. This will
  59. be the last command as it is followed by two separation characters on separate
  60. lines.
  61. @
  62. @
  63.  
  64.     Each command that is to be recognised by the help program MUST
  65.     occupy exactly 9 characters (pad on the right with blanks as needed),
  66.     be in UPPER CASE and be followed immediately by a CR and an LF.
  67.     The prompt for that help screen, which will be located on line 25,
  68.     follows immediately after the command, and should be 70 characters or
  69.     less. The help text immediately follows the prompt and may be up to 24
  70.     screen lines long. The text can contain embedded codes to change the
  71.     attribute of the characters being written. These are entered with a
  72.     backslash followed by TWO (must be two) hex digits which specify the
  73.     color/attribute of the characters which follow,    until a new embedded
  74.     code appears. For example \70 TITLE \07 if it appeared in the help
  75.     text would display "TITLE" and the spaces either side of it in reverse
  76.     video, and subsequent text in regular video. A backslash character
  77.     can be inserted in the text using \\. Tabs are expanded and CR/LF
  78.     combinations are properly interpreted. The whole help text MUST be
  79.     terminated with TWO separation characters following each other on
  80.     separate lines. Note that the commands MUST be placed in the help file
  81.     in alphabetical order, if entries are going to be able to be found
  82.     where the entry characters are the same e.g. the command PRINT will
  83.     only be found if it preceeds the command PRINTER in the help text.
  84.  
  85.     To make the help program from the help text, run HBUILD with the
  86.     following syntax:
  87.  
  88.     HBUILD * [D:][PATH]HELPTEXT.EXT [D:][PATH]PROGNAME.COM
  89.  
  90.     This will cause HBUILD to load the file HELPTEXT.EXT into memory,
  91.     index the commands and then, if there are no errors in the format
  92.     of the help text, write a file called PROGNAME.COM. If drive and
  93.     path are not specified then HBUILD will use the default drive and
  94.     directory.
  95.  
  96.     PROGNAME.COM then contains the HBUILD "help engine" with the indexed
  97.     contents of HELPTEXT.EXT attached to it in the same file. To use
  98.     PROGNAME.COM, simply type :
  99.  
  100.     PROGNAME [TOPIC]
  101.  
  102.     at the DOS prompt, and you will be presented with the help screen
  103.     indexed to the command TOPIC (if it was included on the DOS command
  104.     line). If the help topic was not included on the command line, or    the
  105.     name supplied does not appear in the index in PROGNAME, then you will
  106.     be presented with the screen defined at the head of the help text,
  107.     which should include a list of available commands.
  108.  
  109.     The command interpreter will match on less than the total number
  110.     of characters in the command typed in at the prompt (or at the
  111.     command line), and will find the FIRST command that matches those
  112.     characters input; case is ignored. For example if the help text
  113.     contains the commands DISKCOMP and DISKCOPY, then the user input
  114.     DISKC will find DISKCOMP (assuming the help text had them in
  115.     alphabetical order). The user input of DISKCOP will find DISKCOPY.
  116.     To terminate the program you can press the ENTER key with no input.
  117.  
  118.     Note that PROGNAME.COM contains the same program code as the
  119.     original HBUILD.COM file, so if you want, you could use PROGNAME
  120.     to update itself with a command like:
  121.  
  122.     PROGNAME * HELPTEXT.MOD PROGNAME.COM
  123.  
  124.  
  125.                     David Gwillim
  126.                     1414 N. Catalina Street
  127.                     Los Angeles  CA 90027
  128.                     16 December 1985
  129.  
  130. #
  131. ;
  132. IF1
  133.     %OUT    ************
  134.     %OUT    * Pass One *
  135.     %OUT    ************
  136. ENDIF
  137.  
  138. IF2
  139.     %OUT
  140.     %OUT    ************
  141.     %OUT    * Pass Two *
  142.     %OUT    ************
  143. ENDIF
  144.  
  145. LF    EQU    0AH
  146. CR    EQU    0DH
  147. CRTMode    EQU    449H            ;ROM BIOS data area address
  148. MaxSize    EQU    65400            ;Base figure for help text size
  149.                     ; computation (allows 135 bytes
  150.                     ; for stack space)
  151. Cseg    SEGMENT
  152.     ASSUME CS:Cseg,DS:Cseg,ES:Cseg,SS:Cseg
  153.     ORG    100H
  154.  
  155. Start:    Mov    AH,30H            ;Check DOS version
  156.     Int    21H
  157.     Cmp    AL,2            ;Version 2 or greater?
  158.     Jnl    H00
  159.     Mov    DX,Offset BadDos    ;Print wrong DOS message
  160.     Call    PText
  161.     Mov    AX,4C01H        ;Set error code & terminate process
  162.     Int    21H
  163.     
  164. H00:    Sub    AX,AX            ;Make a zero
  165.     Mov    DS,AX            ;Point to ABS0 segment
  166.     Mov    SI,CRTMode        ;Point to CRTMode byte
  167.     Lodsb
  168.     Cmp    AL,7            ;Mode 7 = Monochrome screen?
  169.     Jne    H0            ; if no, use color default
  170.     Mov    ScrnAdd,0B000H        ;Point to monochrome screen memory
  171. H0:    Push    CS
  172.     Pop    DS
  173.     Mov    SI,81H            ;Point to DOS command tail
  174. H1:    Lodsb
  175.     Cmp    AL,' '            ;Skip any blanks
  176.     Je    H1
  177.     Cmp    AL,'*'            ;Check for build option
  178.     Jne    H2
  179.     Jmp    BuildHelp        ;We are making a help file
  180. H2:    Cmp    AL,CR            ;Any command tail?
  181.     Je    H5            ;If no, go interactive
  182.     Mov    DI,Offset Cmd        ;Place to store command tail
  183.     Mov    CX,9            ;Transfer 9 characters maximum
  184. H3:    Cmp    AL,CR            ;Transfer command tail
  185.     Je    H4
  186.     Inc    CmdLen
  187.     Stosb
  188.     Lodsb
  189.     Loop    H3
  190. H4:    Call    GC0            ;Jump into middle of GetCmd
  191.     Jmp    H8            ;Display help text
  192. H5:    Mov    DX,Current        ;Select current screen
  193. H6:    Call    PHelp            ;Display help text
  194. H7:    Call    GetCmd            ;Get next command
  195.     Cmp    CmdLen,0        ;Just a <RETURN> entered?
  196.     Je    H5
  197.     Cmp    CmdLen,1        ;Single character input line?
  198.     Jne    H8            ; if so, exit program
  199.     Mov    AL,Cmd            ;What's the character that was input?
  200.     Cmp    AL,ExitChr        ;Is it the exit character?
  201.     Jne    H8
  202.     Call    ClrScr            ;Clean up the screen before we leave
  203.     Mov    AX,4C00H        ;Set error code & terminate process
  204.     Int    21H
  205. H8:    Call    GetMatch        ;Find offset to help text
  206.     Cmp    DX,0            ;Help text found?
  207.     Je    H5            ;If not get another command
  208.     Mov    Current,DX        ;Command found, print it
  209.     Jmp    H6            ;Do it all over again
  210.  
  211. ; Clear screen
  212. %OUT    -    ClrScr
  213. ClrScr    proc    near
  214.     Mov    BH,07            ;Clear screen with NORMAL attribute
  215.     MOV    AX,0600H        ; using "scroll active page up"
  216.     MOV    CX,0            ; Upper left corner coords (0,0)
  217.     MOV    DX,184FH        ; Lower right corner coords (79,24)
  218.     INT    10H
  219.     MOV    AH,2            ;Set cursor position
  220.     MOV    BH,0            ;Page 0
  221.     MOV    DX,0H            ;Coords (0,0)
  222.     INT    10H
  223.     Mov    ScrnPos,0        ;Point to beginning of the screen
  224.     RET
  225. ClrScr    endp
  226.  
  227. ;    Get the input command from the user
  228. %OUT    -    GetCmd
  229. GetCmd    proc    near
  230.     Mov    DI,Offset CmdLen    ;Initialize buffer to zeros
  231.     Mov    AL,0
  232.     Mov    CX,10
  233.     Rep    Stosb
  234.     Mov    DX,Offset CmdBuff    ;Point to command input buffer
  235.     Mov    AH,0AH            ;Request edited input from DOS
  236.     Int    21H
  237. GC0:    Sub    CX,CX            ;Zero out CX
  238.     Mov    CL,CmdLen        ;Get input command length
  239.     Inc    CX            ;To permit handling null input
  240.     Mov    SI,Offset Cmd        ;Point to input command
  241.     Mov    DI,SI            ; for Lodsb and Stosb
  242. GC1:    Lodsb                ;Get the next char from Cmd string
  243.     Cmp    AL,'a'            ;Upper case any lower case characters
  244.     Jl    GC2
  245.     Cmp    AL,'z'
  246.     Jg    GC2
  247.     And    AL,5FH
  248.     Cmp    AL,CR            ;End of input line?
  249.     Jne    GC2
  250.     Mov    AL,0            ;Terminate input with a 0 byte
  251. GC2:    Stosb
  252.     Loop    GC1
  253.     Ret
  254. GetCmd    endp
  255.  
  256. ;    Print prompt for next command
  257. %OUT    -    PPrompt
  258. ;Entry: DX contains offset to prompt string terminated in a 0 byte
  259. PPrompt    proc near
  260.     Mov    ScrnPos,3840        ;Point to cursor position (0,24)
  261.     Call    FText            ;Print the prompt
  262.     Push    DX            ;Save returned pointer to help text
  263.     MOV    BH,0            ; on page 0
  264.     MOV    DH,18H            ; to row 24
  265.     Mov    AX,ScrnPos        ;Get last screen location printed + 1
  266.     Sub    AX,3840            ;Get # bytes into row 24
  267.     Shr    AX,1            ;Divide by 2 to get cursor position
  268.     Mov    DL,AL            ; and put cursor there
  269.     MOV    AH,2            ;Set cursor position
  270.     INT    10H
  271.     Mov    ScrnPos,0        ;Point to the top of the screen again
  272.     Pop    DX            ;Restore pointer to help text
  273.     RET
  274. PPrompt    endp
  275.  
  276. %OUT    -    GetMatch
  277. GetMatch    proc    near
  278.     Mov    BX,HelpTxt        ;Point to start of command table
  279.     Mov    DX,0            ;Initialize DX
  280. GM1:    Cmp    BX,0            ;Pointer to next command in table = 0?
  281.     Je    GM3            ;if so, we are at the end of the table
  282.     Mov    DI,BX            ;Store start offset of command
  283.     Sub    CX,CX            ;Zero out CX
  284.     MOV    CL,CmdLen        ;Retrieve length of entered command
  285.     MOV    SI,Offset Cmd        ;Point to entered command
  286.     REPZ    CMPSB            ;Compare them
  287.     Jne    GM2            ;If they weren't equal, try next cmd
  288.     Add    BX,11            ;Jump over the command and pointer
  289.     MOV    DX,BX            ;This is the address of the prompt
  290. GM2:    CMP    DX,0            ;Was there a match?
  291.     Jne    GM3            ;If yes, then return
  292.     Mov    BX,[BX+9]        ;Get pointer to start of next command
  293.     Jmp    GM1            ;Go check for a match with it
  294. GM3:    RET
  295. GetMatch    endp
  296.  
  297. %OUT    -    PHelp
  298. PHelp    proc near
  299.     PUSH    DX            ;Save the offset to the prompt
  300.     CALL    ClrScr            ;Clear the screen
  301.     POP    DX            ;Restore the offset to the prompt
  302.     Call    PPrompt            ;Print prompt for next command
  303.     Inc    DX            ;Point DX to help text
  304.     CALL    FText            ;Display the help text
  305. PH1:    RET
  306. PHelp    endp
  307.  
  308. ;Print a piece of text
  309. ;Entry: DX points to start of text which is terminated in a 0 byte
  310. ;Exit : DX points to byte following 0 terminating byte
  311. %OUT    -    FText
  312. FText    proc    near
  313.     Mov    SI,DX            ;Point to text string with SI
  314.     Mov    DI,ScrnPos        ;Pick up the current screen position
  315.     Push    ES            ;Save ES
  316.     Mov    ES,ScrnAdd        ;Point ES to current screen memory
  317.     Mov    AH,7            ;Default attribute
  318.     Mov    CX,0            ;Start in column 0
  319. PutScr:    Lodsb                ;Get byte from Buffer
  320.     Cmp    AL,0            ;End of text?
  321.     Je    Out
  322.     Cmp    AL,'\'            ;Is this a change of attribute
  323.     Jne    L3
  324.     Call    GetAttrib        ;Read the next byte as new attribute
  325.     Jmp    PutScr
  326. L3:    Cmp    AL,CR            ;Is it a CR
  327.     Jne    L3A
  328.     Call    Pad            ;If so pad to end of line with blanks
  329.     Jmp    PutScr
  330. L3A:    Cmp    AL,9            ;Is it a tab character
  331.     Jne    L4
  332.     Call    FExpandTab        ;If so, expand it (8 space column)
  333.     Jmp    PutScr
  334. L4:    Cmp    AL,LF
  335.     Je    PutScr            ;Ignore line feeds
  336. ToScr:    Stosw
  337.     Inc    CH            ;Keep track of column position
  338.     Jmp    PutScr
  339. Out:    Mov    ScrnPos,DI        ;Store screen position
  340.     Pop    ES            ;Restore ES register
  341.     Mov    DX,SI            ;Return next position in text
  342.     Ret
  343. FText    endp
  344.  
  345. %OUT    -    FExpandTab
  346. FExpandTab    proc near
  347.     Push    AX            ;Save current attribute
  348.     Cmp    CH,71            ;Are we in column 72 or more?
  349.     Jg    FET2            ; if so just do a CR,LF
  350.     Mov    AX,CX            ;Put the column position in AL
  351.     XChg    AH,AL
  352.     Sub    AH,AH
  353.     Cmp    AL,0            ;Make sure no divide by zero!
  354.     Je    FET1
  355.     Div    Eight            ;Find out how far past last tab col
  356. FET1:    Xchg    AH,AL            ;Compute number of spaces to next
  357.     Mov    AH,8
  358.     Sub    AH,AL
  359.     Add    CH,AH            ;Keep track of line position
  360.     Mov    CL,AH            ;Number of spaces to print
  361.     Pop    AX            ;Get attribute byte
  362.     Push    CX            ;Save current value of line pos
  363.     Sub    CH,CH            ;Store count of spaces to display
  364.     Mov    AL,' '            ;Space character
  365.     Rep    Stosw            ;Write to the screen
  366.     Pop    CX            ;Restore CX
  367.     Ret
  368. FET2:    Pop    AX
  369.     Call    Pad            ;Pad line out to 80 columns
  370.     Ret
  371. FExpandTab    endp
  372.  
  373. %OUT    -    Pad
  374. Pad    Proc    Near
  375.     Mov    CL,80
  376.     Sub    CL,CH            ;Compute how many columns left
  377.     Je    EndPad            ;If zero we are in column 80. 
  378.     Sub    CH,CH            ;So we can add CL to DI
  379.     Shl    CX,1            ;Double CX to allow for attribute byte
  380.     Add    DI,CX            ;Pad columns to 80 by incrementing DI
  381. EndPad:    Sub    CH,CH            ;Reset column position counter to 0
  382.     Ret
  383. Pad    Endp
  384.  
  385. %OUT    -    GetAttrib
  386. GetAttrib    proc    near
  387.     Push    CX            ;Save CX register
  388.     Push    AX            ;Save current attribute in AH
  389.     Sub    AH,AH            ;Start with 0 in AH
  390.     Mov    CX,2            ;Accept 2 hex digits only
  391. GA1:    Lodsb                ;Treat next character as attribute
  392.     Cmp    AL,'\'
  393.     Je    Literal            ;Another \ treat as a literal char
  394.     Sub    AL,30H            ;Make ASCII digit binary
  395.     Jl    GAOut            ;Check if too low
  396.     Cmp    AL,9
  397.     Jle    GA2
  398.     And    AL,5FH            ;It wasn't 0 - 9 so upper case it
  399.     Sub    AL,7            ;Make A - F into binary 10 - 15
  400.     Cmp    AL,10            ;Less than A?
  401.     Jl    GAOut            ;Too low for A - F
  402.     Cmp    AL,15            ;Greater than F?
  403.     Jg    GAOut
  404. GA2:    Add    AH,AL            ;Accumulate hex digit
  405.     Cmp    CX,2            ;Is this the first digit
  406.     Jne    GA3
  407.     Push    CX            ;First hex digit so multiply by 16
  408.     Mov    CL,4
  409.     Shl    AH,CL
  410.     Pop    CX
  411.     Loop    GA1            ;Get the 2nd digit
  412. GA3:    Pop    CX            ;Throw away saved AX register
  413.     Pop    CX            ;Restore original CX register
  414.     Mov    AL,0            ;Signify satifactory conversion
  415.     Ret                ;AH contains new character attribute
  416.  
  417. GAOut:    Pop    AX            ;If get here was an invalid hex number
  418.     Pop    CX            ; or a literal '\'
  419.     Ret
  420. Literal:
  421.     Pop    AX            ;Restore registers
  422.     Pop    CX
  423.     Stosw                ;Put a \ to the screen
  424.     Inc    CH            ;Keep track of column position
  425.     Ret
  426. GetAttrib    Endp
  427.  
  428. %OUT     -    BuildHelp
  429. BuildHelp:
  430.     Call    GetNames        ;Get the file names for build
  431.     Mov    DX,Offset Author    ;Print copyright
  432.     Call    PText
  433.     Mov    DX,Offset BHMsg        ;Tell user we are doing build
  434.     Call    PText
  435.     Call    LoadTxt            ;Load help text into memory
  436.     Call    SaveFile        ;Index the text & save it as a pgm
  437.     Mov    DX,Offset BHDone    ;Tell user we are donw
  438.     Call    PText
  439.     Mov    AX,4C00H        ;Set error code & terminate process
  440.     Int    21H
  441.  
  442. ;Print a piece of text
  443. ;Entry: DX points to start of text which is terminated in a 0 byte
  444. %OUT    -    PText
  445. PText    proc    near
  446.     MOV    SI,DX            ;Pointer to text start
  447. PT1:    Lodsb
  448.     Cmp    AL,0            ;Are we at the end of the text?
  449.     Je    PT3
  450. ;    Cmp    AL,9            ;Tab character
  451. ;    Jne    PT2
  452. ;    Call    ExpandTab        ;Expand the tab to spaces
  453. ;    Jmp    PT1
  454. PT2:    Mov    BL,7            ;Normal foreground color
  455.     Mov    AH,0EH            ;Write teletype function
  456.     Int    10H
  457.     Jmp    PT1
  458. PT3:    RET
  459. PText    endp
  460.  
  461. %OUT    -    GetNames
  462. GetNames    proc near
  463.     Mov    DI,Offset InName    ;Point to 1st name buffer
  464. GN1:    Lodsb                ;Skip any leading spaces
  465.     Cmp    AL,' '
  466.     Je    GN1
  467. GN2:    Cmp    AL,CR            ;End of command tail
  468.     Je    GNErr            ; if so error - no 2nd name
  469.     Cmp    AL,' '            ;Space means end of 1st name
  470.     Je    GN3
  471.     Stosb                ;Store the character in name buffer
  472.     Lodsb
  473.     Jmp    GN2            ;Back for more characters
  474. GN3:    Mov    DI,Offset OutName    ;Point to 2nd name
  475. GN4:    Lodsb                ;Get next character
  476.     Cmp    AL,' '            ;Skip any leading spaces
  477.     Je    GN4
  478. GN5:    Cmp    AL,CR            ;End of command tail
  479.     Je    GN6
  480.     Cmp    AL,' '
  481.     Je    GN6
  482.     Stosb
  483.     Lodsb
  484.     Jmp    GN5
  485. GN6:    Ret
  486.  
  487. GNErr:    Mov    DX,Offset BHErr
  488.     Call    PText
  489.     Pop    AX            ;Clean up the stack
  490.     Mov    AX,4C01H        ;Set error code & terminate process
  491.     Int    21H
  492. GetNames    endp
  493.  
  494. %OUT    -    LoadTxt
  495. LoadTxt    proc near
  496.     Mov    DX,Offset InName    ;Point to file name
  497.     Mov    AL,0            ;read access
  498.     Mov    AH,3dH            ;Open the file
  499.     Int    21H
  500.     Jc    LTErr            ;If we get an error, report it
  501.     Mov    Handle,AX        ;Store the returned handle
  502.     Mov    BX,AX            ;File handle for read file
  503.     Mov    DX,Offset SepChar    ;Address of file buffer start
  504.     Mov    CX,MaxSize        ;Calculate max number of bytes to read
  505.     Sub    CX,EndPgm        ;allowing 128 bytes for .COM pgm stack
  506.     Mov    MaxBytes,CX        ;Save the requested number of bytes
  507.     Mov    AH,3FH            ;Read file/device function
  508.     Int    21H
  509.     Jc    LTErr            ;Report any error
  510.     Cmp    AX,MaxBytes        ;Same read as asked for?
  511.     Je    LTLenErr        ;Almost certainly, file too long
  512.     Mov    BytesRead,AX        ;Store number of bytes read in
  513.     Mov    BX,Handle        ;Close file
  514.     Mov    AH,3EH            ;Close file function
  515.     Int    21H
  516.     Ret
  517. LTErr:    Mov    DX,Offset LoadErr    ;Print error message
  518.     Call    PText
  519.     Pop    AX            ;Clean up the stack
  520.     Mov    AX,4C01H        ;Set error code & terminate process
  521.     Int    21H
  522. LTLenErr:
  523.     Mov    DX,Offset LenErr    ;Print error message - file too long
  524.     Call    PText
  525.     Pop    AX            ;Clean up the stack
  526.     Mov    AX,4C01H        ;Set error code & terminate process
  527.     Int    21H
  528. LoadTxt    endp
  529.  
  530. %OUT    -    SaveFile
  531. SaveFile    proc near
  532.     Mov    Current,Offset Buffer + 11 ;Store pointer to first screen
  533.     Mov    DI,Offset Buffer + 9    ;Initialize pointer for cmd address
  534.     Mov    SI,Offset Buffer    ;Point to start of text
  535. SF1:    Lodsb                ;Main loop for commands starts here
  536.     Cmp    AL,SepChar        ;End of help text file?
  537.     Je    SF6
  538.     Mov    CX,9
  539. SF2:    Lodsb
  540.     Cmp    AL,CR            ;End of a command?
  541.     Je    SF3
  542.     Loop    SF2
  543.     Jmp    SFCErr            ;We fell out of loop = error
  544. SF3:    Cmp    CX,1            ;We should have been on last iteration
  545.     Jne    SFCErr            ;If not, error in command length
  546.     Mov    DI,SI            ;Point DI to storage for next cmd addr
  547.     Dec    DI
  548. SF4:    Lodsb                ;Look for end of prompt string
  549.     Cmp    AL,CR            ;End of help text?
  550.     Jne    SF4
  551.     Mov    byte ptr [SI-1],0    ;Terminate prompt with 0 byte
  552. SF5:    Lodsb
  553.     Cmp    AL,SepChar        ;Look for end of help text
  554.     Jne    SF5
  555.     Mov    byte ptr [SI-1],0    ;Terminate text with 0 byte
  556.     Cmp    byte ptr [SI],CR    ;Should be a CR, error if not
  557.     Jne    SFTErr
  558.     Add    SI,2            ;Skip past CRLF following SepChar
  559.     Mov    [DI],SI            ;SI points to next command, store it
  560.     Jmp    SF1            ;Keep indexing help text
  561. SF6:    Mov    word ptr [DI],0        ;Signify the end of the help text
  562.     Mov    byte ptr [SI-1],0    ;Terminate the text with 0 byte
  563.     Mov    LastOfs,SI        ;Store end of memory used
  564.  
  565. ; Now we have indexed the help text, write it plus the "engine" to disk
  566.  
  567.     Mov    DX,Offset OutName    ;Open output file
  568.     Mov    CX,0            ;Normal file attribute
  569.     Mov    AH,3CH            ;Create file function
  570.     Int    21H
  571.     Jnc    SF7
  572.     Mov    DX,Offset SFErr1    ;Report any error
  573.     Jmp    SFErr            ;In case of error
  574. SF7:    Mov    Handle,AX        ;Store handle
  575.     Mov    BX,AX            ;Handle for write
  576.     Mov    DX,100H            ;Write whole pgm to disk file
  577.     Mov    CX,LastOfs        ;Last memory location used
  578.     Sub    CX,DX            ;Allow for PSP in byte count
  579.     Mov    AH,40H            ;Write file function
  580.     Int    21H
  581.     Jnc    SF8
  582.     Mov    DX,Offset SFErr2    ;Report any error
  583.     Jmp    SFErr
  584. SF8:    Mov    BX,Handle        ;Close file
  585.     Mov    AH,3EH            ;Close file function
  586.     Int    21H
  587.     Ret
  588. SFErr:    Call    PText
  589.     Pop    AX            ;Clean up the stack
  590.     Mov    AX,4C01H        ;Set error code & terminate
  591.     Int    21H
  592.  
  593. SFCErr:    Mov    byte ptr [SI],0        ;Terminate text with 0 byte
  594.     Push    DI            ;Save the pointer to start of command
  595.     Mov    DX,Offset HCErr        ;Print 'Error in command ... '
  596.     Call    PText
  597.     Pop    DI
  598.     Mov    DX,[DI]            ;Get address to bad area
  599.     Call    PText
  600.     Mov    AX,4C01H        ;Set error code & terminate
  601.     Int    21H
  602.  
  603. SFTErr:    Push    SI            ;Save pointer to byte following error
  604.     Mov    DX,Offset HTErr        ;Print 'Error in text ... '
  605.     Call    PText
  606.     Pop    SI            ;Recover pointer to bad byte
  607.     Mov    Byte ptr [SI+60],0    ;Limit text display to one line
  608.     Mov    DX,SI            ;Get address to bad area
  609.     Call    PText
  610.     Mov    AX,4C01H        ;Set error code & terminate
  611.     Int    21H
  612. SaveFile    endp
  613.  
  614. %OUT    -    Variables
  615. Eight    Db    8
  616. BadDos    Db 'HBUILD needs DOS version 2.0 or greater',CR,LF,0
  617. BHMsg    Db 'Building Help Program',CR,LF,LF,0
  618. BHErr    Db 'USAGE:',CR,LF,9
  619.     DB 'HBUILD * [D:][Path]HelpFile.Ext [D:][Path]OutFile.COM',CR,LF,0
  620. BHDone    Db 'Build Help successfully completed',CR,LF,0
  621. LoadErr    Db 'Error: Cannot read input file',CR,LF,0
  622. LenErr    Db 'Error: Help file too long to use',CR,LF,0
  623. SFErr1    Db 'Error: Cannot open output file',CR,LF,0
  624. SFErr2    Db 'Error: Cannot close output file',CR,LF,0
  625. HTErr    Db 'Error: Misplaced separation character prior to -->',CR,LF,0
  626. HCErr    Db 'Error: Help command not 9 characters long --> ',0
  627.  
  628. InName    Db    64 Dup(0)
  629. OutName    Db    64 Dup(0)
  630. ScrnAdd    Dw    0B800H            ;Default of color graphics screen
  631. ScrnPos    DW    0            ;Position in screen buffer
  632. Handle    Dw    0
  633. BytesRead    Dw    0        ;Number of bytes read from help text
  634. MaxBytes    Dw    0        ;Maximum number of bytes in Buffer
  635. LastOfs        Dw    0        ;Last offset used by help text
  636. Current        Dw    Offset Null    ;Current help screen address
  637. CmdBuff    Db    9            ;User input command buffer
  638. CmdLen    Db    0            ; as per DOS function 0AH layout
  639. Cmd    Db    9 Dup(0)
  640. Null    Db    '\70 PRESS RETURN \07',0,0
  641. Author    Db    'HELP BUILD Version 1.6 - 16 December 1985',CR,LF
  642.     Db    'Copyright (C) 1985 by David Gwillim ',CR,LF,0
  643. HelpTxt    Dw    Offset Buffer
  644. EndPgm    Dw    $
  645.  
  646. SepChar    Db    0            ;Separation character for help file
  647.     Db    2 Dup(0)        ;Space for CRLF following SepChar
  648. ExitChr    Db    0            ;Exit character
  649.     Db    2 Dup(0)        ;Space for CRLF following ExitChr
  650. Buffer    Db    0            ;Start of help text proper
  651. Cseg    Ends
  652.     End    Start
  653.