	page ,132
;	SCCSID = @(#)tcmd2a.asm 4.1 85/06/25
;	SCCSID = @(#)tcmd2a.asm 4.1 85/06/25
TITLE	PART5 COMMAND Transient routines.
;/*
; *                      Microsoft Confidential
; *                      Copyright (C) Microsoft Corporation 1991
; *                      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

	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
	pop	bx   			; BL = /debug flag
	or	bl,bl
	jz	verDone			; /debug is false - we're done

;*	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
;M032	and	al,7			; AL = DOS internal revision
	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,'A'			; AL = DOS internal rev letter
	mov	One_Char_Val,al
	mov	dx,offset TRANGROUP:DosRev_Ptr
	invoke	Std_Printf		; print DOS internal revision

	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
	invoke	find_prompt			; LOOK FOR PROMPT STRING
	jc	PP0				; CAN'T FIND ONE
	cmp	byte ptr es:[di],0
	jnz	PP1
PP0:
	call	print_drive			; USE DEFAULT PROMPT
	mov	al,sym
	call	print_char
	jmp	short PP5

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	PP1

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	PP1

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

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
;M022	mov	bh.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
