        page ,132
TITLE   PART5 COMMAND Transient routines.
;
;                        IBM Confidential
;                        Copyright (C) IBM Corporation 1991-1993
;                        All Rights Reserved.
;

;       Revision History
;       ================
;       M01     md 7/13/90      Changed CLS to access ROM BIOS data directly
;
;       M013    SR      08/06/90        Changed Version to use new call to
;                               get info about DOS in HMA or ROM.
;       M018    md      08/12/90        Increment screen height by 1 when
;                                       obtained from ROM BIOS.
;       M022    md      08/29/80        Set correct video page in REG_CLS
;
;       ABx000          01/30/92        DOS 5.00.1 Refresh (Carla Bruner)
;                                       Always show revision level for VER.
;               MARMAR  08/16/93        Added Bambi flush support


        INCLUDE comsw.asm

.xlist
.xcref
        include dossym.inc
        include bpb.inc
        include syscall.inc
        include filemode.inc
        include sf.inc
        include comequ.asm
        include comseg.asm
        include ioctl.inc
        include rombios.inc             ;M01
.list
.cref


CODERES         SEGMENT PUBLIC BYTE     ;AC000;
CODERES         ENDS

DATARES         SEGMENT PUBLIC BYTE     ;AC000;
DATARES         ENDS

TRANDATA        SEGMENT PUBLIC BYTE     ;AC000;
        EXTRN   arg_buf_ptr:word
        EXTRN   BadCurDrv:byte          ;AC000;
        EXTRN   clsstring:byte
        EXTRN   dback_ptr:word
        EXTRN   display_ioctl:word      ;AN000;
        EXTRN   display_width:word      ;AN000;
        EXTRN   DosHma_Ptr:word
        EXTRN   DosLow_Ptr:word
        EXTRN   DosRev_Ptr:word
        EXTRN   DosRom_Ptr:word
        EXTRN   Extend_buf_ptr:word     ;AN049;
        EXTRN   linperpag:word          ;AN000;
        EXTRN   msg_disp_class:byte     ;AN049;
        EXTRN   nulpath_ptr:word
        EXTRN   Parse_Ver:byte
        EXTRN   prompt_table:word
        EXTRN   string_buf_ptr:word     ;AC000;
        EXTRN   vermes_ptr:word
TRANDATA        ENDS

TRANSPACE       SEGMENT PUBLIC BYTE     ;AC000;
        EXTRN   Arg_Buf:byte
        EXTRN   bwdbuf:byte
        EXTRN   curdrv:byte
        EXTRN   dirchar:byte
        EXTRN   major_ver_num:word
        EXTRN   minor_ver_num:word
        EXTRN   One_Char_Val:byte
        EXTRN   srcxname:byte           ;AN049;
        EXTRN   string_ptr_2:word
TRANSPACE       ENDS

TRANCODE        SEGMENT PUBLIC BYTE

ASSUME  CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING

;---------------

TRANSPACE       SEGMENT PUBLIC BYTE     ;AC000;
        EXTRN   arg:byte                ; the arg structure!
transpace       ends
;---------------

        EXTRN   cerror:near             ;AN049;
        EXTRN   crlf2:near
        EXTRN   drvbad:near
        EXTRN   std_printf:near

        PUBLIC  build_dir_for_chdir
        PUBLIC  build_dir_for_prompt
        PUBLIC  build_dir_string
        PUBLIC  cls
        PUBLIC  path
        PUBLIC  print_char
        PUBLIC  print_drive
        PUBLIC  print_version
        PUBLIC  print_b
        PUBLIC  print_back
        PUBLIC  print_eq
        PUBLIC  print_esc
        PUBLIC  print_g
        PUBLIC  print_l
        PUBLIC  print_prompt
        PUBLIC  version


        break   Version

;***    Version - display DOS version
;
;       SYNTAX  ver [/debug]
;
;               /debug - display additional DOS configuration info
;
;       ENTRY   command-line tail is in PSP
;
;       EXIT    if successful, nothing
;               if parse fails,
;                 parse error message is set up (for Std_EPrintf)
;                   AX = system parser error code
;                   DX = ptr to message block
;                 we jump to CError
;
;       EFFECTS
;         If parse fails, a parse error message is displayed.
;         Otherwise, version message is displayed.
;         If /debug is specified, additional DOS info is displayed.

Version:
        assume  ds:TRANGROUP,es:TRANGROUP

;       Parse command line for /debug switch.

        mov     si,81h                          ; DS:SI = ptr to command tail
        mov     di,offset TRANGROUP:Parse_Ver   ; ES:DI = ptr to parse block
        xor     cx,cx                           ; CX = # positional param's found
        invoke  Parse_With_Msg

        mov     bl,1                    ; BL = flag = /debug present
        cmp     ax,RESULT_NO_ERROR
        je      verPrintVer             ; something parsed - must be /debug
        dec     bl                      ; BL = flag = no /debug present
        cmp     ax,END_OF_LINE
        je      verPrintVer             ; reached end of line - ok

;       The parse failed.  Error message has been set up.

        jmp     CError

verPrintVer:
        push    bx                      ; save /debug flag
        call    Crlf2
        call    Print_Version
        call    Crlf2

;*      For /debug, display DOS internal revision and DOS location
;       (low memory, HMA, or ROM).

;       Bugbug: use symbols for bitmasks below.

        mov     ax,(SET_CTRL_C_TRAPPING shl 8) + 6 ; M013
        int     21h
        mov     al,dl                   ;revision number in dl; M013
        mov     bh,dh                   ;flags in dh now; M013
        cmp     al,'Z'-'A'      ;M032   ; revision in A-to-Z range?
        jbe     @f              ;M032   ; A-to-Z revision ok
        mov     al,'*'-'A'      ;M032   ; beyond Z, just say revision *
@@:     add     al,'0'                  ; AL = DOS internal rev letter
                                        ; ABC000 previously 'A'
        mov     One_Char_Val,al
        mov     dx,offset TRANGROUP:DosRev_Ptr
        invoke  Std_Printf              ; print DOS internal revision

;ABC000 Moved here such that VER always displays revision level.
        pop     dx                      ; BL = /debug flag
        or      dl,dl
        jz      verDone                 ; /debug is false - we're done

        mov     cl,4
        shr     bh,cl                   ; CY = DOS in ROM
        jc      verRom
        shr     bh,1                    ; CY = DOS in HMA
        jc      verHma

;       DOS isn't in ROM or HMA, so it must be in lower memory.

        mov     dx,offset TRANGROUP:DosLow_Ptr
        jmp     short verPrintLoc
verRom: mov     dx,offset TRANGROUP:DosRom_Ptr
        jmp     short verPrintLoc
verHma: mov     dx,offset TRANGROUP:DosHma_Ptr
verPrintLoc:
        invoke  Std_Printf
verDone:
        jmp     Crlf2

Print_Version:
        mov     ah,GET_VERSION
        int     21h
        push    ax
        xor     ah,ah
        mov     Major_Ver_Num,ax
        pop     ax
        xchg    ah,al
        xor     ah,ah
        mov     Minor_Ver_Num,ax
        mov     dx,offset TRANGROUP:VerMes_Ptr
        jmp     Std_Printf

        assume  ds:TRANGROUP,es:TRANGROUP
print_prompt:
        push    ds
        push    cs
        pop     ds                              ; MAKE SURE DS IS IN TRANGROUP
        push    es
        pushf
bambi_test:
        mov     ax,4a10h                        ; MARMAR start
        mov     bx,0
        int     2fh
        cmp     ax,0babeh                       ; Bambi alive?
        jne     bambi_continue                  ; Bambi is dead, continue....
        cmp     cx,0                            ; Do we have uncommitted blocks?
        jne     flush_bambi                     ; Yes, go flush them
bambi_continue:
        popf
        invoke  find_prompt                     ; LOOK FOR PROMPT STRING
;        int 3
        jc      PP0                             ; CAN'T FIND ONE
        cmp     byte ptr es:[di],0
        jnz     PP1
PP0:
; VCB - Make default PROMPT $P$G
;       call    print_drive                     ; USE DEFAULT PROMPT
;       mov     al,sym
;       call    print_char
        push    ds
        pop     es
        call    build_dir_for_prompt
        call    print_G
        jmp     short PP5
flush_bambi:
        mov     ax,4a10h
        mov     bx,1h                           ; Commit dirty blocks
        int     2fh
        jmp     bambi_test                      ; MARMAR end
PP1:
        mov     al,es:[di]                      ; GET A CHAR
        inc     di
        or      al,al
        jz      PP5                             ; NUL TERMINATED
        cmp     al,dollar                       ; META CHARACTER?
        jz      PP2                             ; NOPE
PPP1:
        call    print_char
        jmp     SHORT PP1                                             ;AC001;

PP2:
        mov     al,es:[di]
        inc     di
        mov     bx,offset trangroup:prompt_table-3
        or      al,al
        jz      PP5

PP3:
        add     bx,3
        invoke  upconv
        cmp     al,[bx]
        jz      PP4
        cmp     byte ptr [bx],0
        jnz     PP3
        jmp     SHORT PP1                                             ;AC001;

PP4:
        push    es
        push    di
        push    cs
        pop     es
        call    [bx+1]
        pop     di
        pop     es
        jmp     SHORT PP1                                             ;AC001;

PP5:
        pop     es                              ; RESTORE SEGMENTS
        pop     ds
        return


print_back:
        mov     dx,offset trangroup:dback_ptr
        jmp     std_printf

print_EQ:
        mov     al,'='
        jmp     short print_char

print_esc:
        mov     al,1BH
        jmp     short print_char

print_G:
        mov     al,rabracket
        jmp     short print_char

print_L:
        mov     al,labracket
        jmp     short print_char

print_B:
        mov     al,vbar

print_char:

;       Bugbug: Why bother with ds,es here?

        push    es
        push    ds
        pop     es
        push    di
        push    dx
        mov     dl,al                           ;AC000; Get char into al
        mov     ah,Std_CON_output               ;AC000; print the char to stdout
        int     21h                     ;AC000;
        pop     dx
        pop     di
        pop     es
        ret

print_drive:
        mov     ah,Get_Default_drive
        int     21h
        add     al,capital_A
        call    print_char
        ret

ASSUME  DS:TRANGROUP,ES:TRANGROUP

build_dir_for_prompt:
        xor     dl,dl
        mov     si,offset trangroup:bwdbuf
        mov     di,SI
        mov     al,CurDrv
        add     al,'A'
        mov     ah,':'
        stosw
        mov     al,[dirchar]
        stosb
        xchg    si,di
        mov     string_ptr_2,di
        mov     ah,Current_dir
        int     21h
        mov     dx,offset trangroup:string_buf_ptr
        jnc     DoPrint
        mov     dx,offset trangroup:BadCurDrv
DoPrint:
        call    std_printf

        ret

build_dir_for_chdir:
        call    build_dir_string
        mov     dx,offset trangroup:bwdbuf
        mov     string_ptr_2,dx
        mov     dx,offset trangroup:string_buf_ptr
        call    std_printf
        ret

build_dir_string:
        mov     dl,ds:[FCB]
        mov     al,DL
        add     al,'@'
        cmp     al,'@'
        jnz     gotdrive
        add     al,[CURDRV]
        inc     al

gotdrive:
        push    ax
        mov     si,offset trangroup:bwdbuf+3
        mov     ah,Current_dir
        int     21h
        jnc     dpbisok
        push    cs
        pop     ds
        jmp     drvbad

dpbisok:
        mov     di,offset trangroup:bwdbuf
        mov     dx,di
        pop     ax
        mov     ah,':'
        stosw
        mov     al,[dirchar]
        stosb

        ret

        break   Path
assume  ds:trangroup,es:trangroup

PATH:
        xor     al,al                           ;AN049; Set up holding buffer
        mov     di,offset Trangroup:srcxname    ;AN049;   for PATH while parsing
        stosb                                   ;AN049; Initialize PATH to null
        dec     di                              ;AN049; point to the start of buffer
        invoke  PGetarg                         ; Pre scan for arguments
        jz      disppath                        ; Print the current path
        cmp     al,semicolon                    ;AC049; NUL path argument?
        jnz     pathslp                         ;AC049;
        inc     si                              ;AN049; point past semicolon
        jmp     short scan_white                ;AC049; Yes - make sure nothing else on line

pathslp:                                        ; Get the user specified path
        lodsb                                   ; Get a character
        cmp     al,end_of_line_in               ;AC049; Is it end of line?
        jz      path_eol                        ;AC049; yes - end of command

        invoke  testkanj                        ;See if DBCS
        jz      notkanj2                        ;No - continue
        stosb                                   ;AC049; Yes - store the first byte
        lodsb                                   ;skip second byte of DBCS

path_hold:                                      ;AN049;
        stosb                                   ;AC049; Store a byte in the PATH buffer
        jmp     short pathslp                   ;continue parsing

notkanj2:
        invoke  upconv                          ;upper case the character
        cmp     al,semicolon                    ;AC049; ';' not a delimiter on PATH
        jz      path_hold                       ;AC049; go store it
        invoke  delim                           ;delimiter?
        jnz     path_hold                       ;AC049; no - go store character

scan_white:                                     ;AN049; make sure were at EOL
        lodsb                                   ;AN049; get a character
        cmp     al,end_of_line_in               ;AN049; end of line?
        jz      path_eol                        ;AN049; yes - go set path
        cmp     al,blank                        ;AN049; whitespace?
        jz      scan_white                      ;AN049; yes - continue scanning
        cmp     al,tab_chr                      ;AN049; whitespace?
        jz      scan_white                      ;AN049; yes - continue scanning

        mov     dx,offset TranGroup:Extend_Buf_ptr ;AN049; no - set up error message
        mov     Extend_Buf_ptr,MoreArgs_ptr     ;AN049; get "Too many parameters" message number
        mov     msg_disp_class,parse_msg_class  ;AN049; set up parse error msg class
        jmp     cerror                          ;AN049;

path_eol:                                       ;AN049; Parsing was clean
        xor     al,al                           ;AN049; null terminate the PATH
        stosb                                   ;AN049;    buffer
        invoke  find_path                       ;AN049; Find PATH in environment
        invoke  delete_path                     ;AC049; Delete any offending name
        invoke  scan_double_null                ;AC049; Scan to end of environment
        invoke  move_name                       ;AC049; move in PATH=
        mov     si,offset Trangroup:srcxname    ;AN049; Set up source as PATH buffer

store_path:                                     ;AN049; Store the PATH in the environment
        lodsb                                   ;AN049; Get a character
        cmp     al,end_of_line_out              ;AN049; null character?
        jz      got_paths                       ;AN049; yes - exit
        invoke  store_char                      ;AN049; no - store character
        jmp     short store_path                ;AN049; continue

got_paths:                                      ;AN049; we're finished
        xor     ax,ax                           ;null terminate the PATH in
        stosw                                   ;    the environment
        return

disppath:
        invoke  find_path                       ;AN049;
        call    print_path
        call    crlf2
        return

print_path:
        cmp     byte ptr es:[di],0
        jnz     path1

path0:
        mov     dx,offset trangroup:nulpath_ptr
        push    cs
        pop     es
        push    cs
        pop     ds
        jmp     std_printf

path1:
        push    es
        pop     ds
        sub     di,5
        mov     si,di
ASSUME  DS:RESGROUP
        invoke  scasb2                          ; LOOK FOR NUL
        cmp     cx,0FFH
        jz      path0
        push    cs
        pop     es
        mov     di,offset trangroup:arg_buf
        mov     dx,100h
        sub     dx,cx
        xchg    dx,cx
        rep     movsb
        mov     dx,offset trangroup:arg_buf_ptr
        push    cs
        pop     ds
        jmp     std_printf

ASSUME  DS:TRANGROUP

        break   Cls

; ****************************************************************
; *
; * ROUTINE:     CLS
; *
; * FUNCTION:    Clear the screen using INT 10h.  If ANSI.SYS is
; *              installed, send a control string to clear the
; *              screen.
; *
; * INPUT:       command line at offset 81H
; *
; * OUTPUT:      none
; *
; ****************************************************************

assume  ds:trangroup,es:trangroup

ANSI_installed          equ    0ffh

CLS:
        mov     ah,Mult_ANSI                    ;AN000; see if ANSI.SYS installed
        mov     al,0                            ;AN000;
        int     2fh                             ;AN000;
        cmp     al,ANSI_installed               ;AN000;
        jz      ansicls                         ;AN000; installed - go do ANSI CLS

check_lines:
        mov     ax,(IOCTL SHL 8) + generic_ioctl_handle ;AN000; get lines per page on display
        mov     bx,stdout                       ;AN000; lines for stdout
        mov     ch,ioc_sc                       ;AN000; type is display
        mov     cl,get_generic                  ;AN000; get information
        mov     dx,offset trangroup:display_ioctl ;AN000;
        int     21h                     ;AN000;
        jc      no_variable                     ;AN000; function had error, use default
        mov     ax,linperpag                    ;AN000; get number of rows returned
        mov     dh,al                           ;AN000; set number of rows
        mov     ax,display_width                ;AN000; get number of columns returned
        mov     dl,al                           ;AN000; set number of columns
        jmp     short regcls                    ;AN000; go do cls

no_variable:
        mov     bx,stdout                       ;AC000; set handle as stdout
        mov     ax,IOCTL SHL 8                  ;AC000; do ioctl - get device
        int     21h                     ;AC000;    info
        test    dl,devid_ISDEV                  ;AC000; is handle a device
        jz      ANSICLS                         ;AC000; If a file put out ANSI
        test    dl,devid_SPECIAL                ;AC000;
        jnz     cls_normal                      ;AC000; If not special CON, do ANSI

ansicls:
        call    ansi_cls                        ;AN000; clear the screen
        jmp     short cls_ret                   ;AN000; exit

;
; Get video mode
;

cls_normal:                                     ;AC000;

        mov     ah,get_video_state              ;AC000; set up to get video state
        int     video_io_int                    ;AC000; do int 10h - BIOS video IO
        cmp     al,video_alpha                  ;AC000; see if in text mode
        jbe     DoAlpha
        cmp     al,video_bw                     ;AC000; see if black & white card
        jz      DoAlpha
;
; We are in graphics mode.  Bogus IBM ROM does not scroll correctly.  We will
; be just as bogus and set the mode that we just got.  This will blank the
; screen too.
;
        mov     ah,set_video_mode               ;AC000; set video mode call
        int     video_io_int                    ;AC000; do int 10h - BIOS video IO
        jmp     short cls_ret                   ;AC000; exit

DoAlpha:
;
; Get video mode and number of columns to scroll
;

;M01 - INT 10 Function 0F doesn't reliably return the number of rows on some
;M01   adaptors.  We circumvent this by reaching directly into the BIOS data
;M01   area
;M01   Commented out code here is the original
;M01    mov     ah,get_video_state              ;AC000; set up to get current video state
;M01    int     video_io_int                    ;AC000; do int 10h - BIOS video IO
;M01    mov     dl,ah
;M01    mov     dh,linesperpage                 ;AC000; have 25 rows on the screen

;M01   Following code lifted from a fix Compaq applied to ANSI

        push    ds
        MOV     AX,ROMBIOS_DATA         ; GET ROM Data segment  M01
        MOV     DS,AX                   ;  *                    M01
        Assume  DS:ROMBIOS_DATA

        mov     dx,CRT_Cols             ; Get Columns - assume < 256 M01
        MOV     dh,CRT_Rows             ; GET MAX NUM OF ROWS   M01
        pop     ds                      ;                       M01
        Assume  DS:Trangroup

        or      dh,dh                   ; Q:ZERO                M01
        jnz     regcls                  ;  *JMP IF NO           M01

        MOV     dh,LINESPERPAGE         ; SET TO 24 ROWS        M01

regcls:
        inc     dh                      ; height+1              M018
        call    reg_cls                         ; go clear the screen

cls_ret:
        ret                                     ; exit

; ****************************************************************
; *
; * ROUTINE:     REG_CLS
; *
; * FUNCTION:    Clear the screen using INT 10H.
; *
; * INPUT:       DL = NUMBER OF COLUMNS
; *              DH = NUMBER OF ROWS
; *
; * OUTPUT:      none
; *
; ****************************************************************

reg_cls proc    near

;
; Set overscan to black.
;

        dec     dh                              ;  decrement rows and columns
        dec     dl                              ;     to zero base
        push    dx                              ;  save rows,columns
        mov     ah,set_color_palette            ;  set up to set the color to blank
        xor     bx,bx
        int     video_io_int                    ; do int 10h - BIOS video IO
        pop     dx                              ;  retore rows,colums

        xor     ax,ax                           ;  zero out ax
        mov     CX,ax                           ;     an cx
;
; Scroll active page
;
        mov     ah,scroll_video_page            ; set up to scroll page up
        mov     bh,video_attribute              ; attribute for blank line
        xor     bl,bl                           ; set BL to 0
        int     video_io_int                    ; do int 10h - BIOS video IO
;
; Seek to cursor to 0,0
;
;M022 following two lines added
        mov     ah,get_video_state              ; get current video page in BH
        int     video_io_int
        mov     ah,set_cursor_position          ; set up to set cursor position
        xor     dx,dx                           ; row and column 0
        int     video_io_int                    ; do into 10h - BIOS video IO

        ret

reg_cls endp

; ****************************************************************
; *
; * ROUTINE:     ANSI_CLS
; *
; * FUNCTION:    Clear the screen using by writing a control code
; *              to STDOUT.
; *
; * INPUT:       none
; *
; * OUTPUT:      none
; *
; ****************************************************************

ansi_cls proc   near                            ;AC000;

        mov     si,offset trangroup:clsstring
        lodsb
        mov     cl,al
        xor     ch,ch
        mov     ah,Raw_CON_IO
clrloop:
        lodsb
        mov     DL,al
        int     21h
        loop    clrloop
        return

ansi_cls        endp                            ;AC000;

trancode    ends
            end
