* Prompt.Asm
*
*       Written 1/4/87 by C.Heath
*
*       Copyright (c) 1986 by C.Heath of Microsmiths Inc.
*
*       This program may be freely copied for individual use.  It may
* also be freely distributed with the following restrictions:
*
*       1) No modifications to the source code are made.  If an executable
* version of the program is distributed, use assem and blink 6.7, which
* should result in an executable of 340 bytes.
*       2) Please verify that the most current version is distributed.
* This can be verified by contacting "cheath" on BIX, or 74216,2117 on CIS,
* or write to Microsmiths, Inc., PO Box 561, Cambridge, MA 02140.
*       3) The ARP series may be distributed with commercial software
* except as noted in (4) provided it's origin is stated.  Please contact
* me to insure you have the latest version.
*       4) This module may NOT be distributed with any commercial software
* which encourages the BCPL program interface without express written
* permission.  This restriction includes the Metacomco Shell.

*       This module replaces the ADOS "Prompt" command.  It matches the
* ADOS prompt syntax, but also allows imbedded spaces in the prompt command.
*       In addition, it allows a simple path substitution to be made.  This
* must work in tandem with the ARP "CD" command.  To use this, the key
* %p is used on the command line.  Anything following the %p will be
* ignored.
*       This command is smaller than the ADOS equivalent so runs a bit faster.

*       This is installment three of the "ARP" series. Three down, 39 to go.

******  Equates and publics     ***************************************

        INCLUDE "exec/types.i"
        INCLUDE "libraries/dos.i"
        INCLUDE "libraries/dosextens.i"

MIN_LIB         set     $1f             ; Library minimum rev level!
                                        ; ADOS "stack" command

* NOTE: PLENGTH is less than ADOS's so we can use the last two
* bytes as a flag in conjunction with the PATH option

PLENGTH         set     60              ; Maximum length of prompt

CD_FLAG         set     $80             ; Store this flag value in string.
* NOTE, it is assumed no other programs use $80 which is ignored by
*       the console.device.

* This is here for assembler compatability
stl_len         equ     44              ; Length of stl_too_long
                                
*** WITH MANX, SUBSTITUTE public FOR xref
xlib    macro   
        xref    _LVO\1
        endm

*** BEGIN MANX code.  Uncomment the next few lines to assemble with MANX
*
*       entry   .begin
*       public  .begin
*.begin
*** END MANX CODE

        xlib    OpenLibrary
        xlib    CloseLibrary
        xlib    FindTask

        xlib    Output
        xlib    Write

******  The Program             ***************************************

Start:
        move.l  4,a6                    ; ExecBase in A6 unless DOSBase later

        move.l  A0,A2                   ; Register A2 is cmdline henceforth
        cmp     #PLENGTH,D0
         ble.s  length_ok

************************************************************************
*
* Input string too long, PLENGTH character limit.
*       Print error and exit.
*
************************************************************************
too_long:
        lea     DOSName(pc),A1          ; Open DOS.library
        moveq.l #MIN_LIB,d0
        jsr     _LVOOpenLibrary(A6)
        or.l    D0,D0
         beq.s  BadExit                 ; Can't!! Return error value...
        move.l  D0,A6                   ; DOSBase in A6 henceforth

        move.l  #str_too_long,D2        ; Set string to Write in D2,D3
        move.l  #stl_len,D3

        jsr     _LVOOutput(A6)          ; Get Output handle
        move.l  D0,D1                   ; It's a calling arg
        jsr     _LVOWrite(A6)           ; Echo "String"

        move.l  A6,A1
        move.l  4,A6                    ; AbsExecBase
        jsr     _LVOCloseLibrary(A6)

        moveq   #5,D0                   ; Return a minimal error
        rts

************************************************************************
*
* BadExit is where to go if there is an error opening the DOS library
*       This should only happen if things are really sick
*
************************************************************************
BadExit:        moveq   #20,D0
                rts

************************************************************************
*
* Proceed with normal code
*       Find Process Base, we need the CLIStruct to store the prompt
*
************************************************************************
length_ok:
        suba.l  A1,A1
        jsr     _LVOFindTask(A6)
        move.l  D0,A3                   ; Process base
        move.l  pr_CLI(A3),D0
         beq.s  BadExit                 ; Not a CLI process. Punt
        asl.l   #2,D0
        move.l  D0,A3                   ; A3 points at CLIStruct henceforth

*
* Process the input command string
*
skpspc: move.b  (A2)+,D0                ; Skip spaces 
        cmp.b   #$20,D0
         beq.s  skpspc
        subq    #1,A2
        cmp.b   #$0A,D0                 ; check for a NULL string ?
         bne.s  ok_string

        lea     default(pc),A2          ; Null input, set to default string!

*
* OK, string (A2) can be copied into the DOS Prompt BSTR
*
*       MCC needs an upper-case N for it's %N test.
* MCC also translates all other chars, but I didn't.
*
ok_string:
        move.l  cli_Prompt(A3),D0       ; Get BSTR pointing to prompt
        asl.l   #2,D0
        move.l  D0,A0                   ; A0 = where to store length
        lea     1(A0),A1                ; A1 = where to store string

* Register A1 is where string is stored
* Register D0 is the length tally
* Register A0 is where to store the length when finished
* Register D2 is last-char flag for %P test

        moveq   #0,D2                   ; Last char for % test
        moveq   #-1,D0                  ; Char count in D0
ll1:    addq    #1,D0                   ; Copy the string
        move.b  (A2)+,D1
         beq.s  ll2
        cmp.b   #$0A,D1
         beq.s  ll2                     ; End of string

        cmp.b   #'%',D2                 ; Check if last char was '%'
         bne.s  ll3                     ; Nope, just copy it

        cmp.b   #'p',D1
         beq.s  DoKluge                 ; DO THE PATH KLUGE
        cmp.b   #'P',D1                 ; PATH SPECIFIED WITH %P
         beq.s  DoKluge

        cmp.b   #'n',D1
         bne.s  ll3
        move.b  #'N',D1                 ; Substitute N for n, for ADOS

ll3:    move.b  D1,(A1)+                ; Save a char in the BSTR
        move.b  D1,D2                   ; Save for % test on next char!
        bra.s   ll1

*
* Finished copying the prompt.  Now set the length and exit.
*
ll2:    move.b  D0,(A0)                 ; Save the length
        moveq.l #0,D0                   ; Program sucess return
        rts                             ; Exit(0)

*
* DoKluge
*       Here, concatenate the current pathname onto the prompt
* string and set the flag, offset bytes.
*
* NOTE: If the resulting string would be too long, just fall back
* and do the same old stupid ADOS stuff.  Sorry...
DoKluge:
        move.l  cli_SetName(A3),D5
        asl.l   #2,D5
        move.l  D5,A4                   ; Get the BSTR for path name
        move.b  (A4),D5                 ; Length of path name
        add.b   D0,D5                   ; combined length
        cmp.b   #PLENGTH-1,D5
         bgt.s  ll3                     ; Safety punt if the CD string
; will make the command line too long.  Just leave the %P in the prompt!

        subq    #1,A1                   ; Offset to start of %P
        addq    #1,A4                   ; Advance past BSTR length... ICK!!!

        move.b  #CD_FLAG,(A1)+

* Loop Here concatenating the Path to the Prompt
kl1:    cmp.b   D0,D5
         ble.s  kl2                     ; exit loop
        move.b  (A4)+,(A1)+
        addq    #1,D0
        bra.s   kl1

kl2:    move.b  #'>',(A1)+              ; Tack on "> "

* The length is in D0, with a bit of hand waving.
        addq    #1,D0
        move.b  D0,(A0)

        moveq   #0,D0                   ; Clean exit
        rts


***************************************************************************
*
* Following is just constant data used by the program
*
***************************************************************************

DOSName:        dc.b    'dos.library',0

str_too_long:   dc.b    'String too long, prompt limited to 58 chars',$0a

default:        dc.b    '> ',$0a

        END
