$NOLIST
	NAME	Compass_II_Console

$INCLUDE (``OsIncs`WinASM~Inc~)

OS_CGROUP	GROUP	OS_CODE

	PUBLIC	ConCharOut, ConLineOut

	EXTRN     CharHeight: FAR
	EXTRN     LineHeight: FAR
	EXTRN     CharWidth: FAR


bitsPerWord	EQU 16
fontOverhead	EQU 8
fastWidth		EQU 8
ellipse		EQU 0F7H
ellipseCh		EQU 086H
shiftRet		EQU 0CDH
shiftRetCh	EQU 080H


csrOn	EQU	1
XHOME	EQU	1
YHOME	EQU	1

CR	EQU	0DH
LF	EQU	0AH
BS	EQU	08H

allOnes	EQU	0FFFFH
MOD16	EQU	000FH
MOD8	EQU	0007H

	EXTRN	BlitRectangle:FAR
	EXTRN	WinScrollRectangle:FAR
	EXTRN	WinEraseRectangle:FAR
	EXTRN	WinInvertLine:FAR
	EXTRN	GetMyWindowState:FAR
	EXTRN	EnterWindows:FAR
	EXTRN	LeaveWindows:FAR

OS_CODE	SEGMENT	PUBLIC	'CODE'
	ASSUME	CS:OS_CGROUP



$EJECT
; PROCEDURE ConCharOut (ch: BYTE);
;
; Char is placed with its top left corner at the point (xLoc, yLoc).
; Xloc is updated by charWidth. Yloc is updated by charHeight + 2.
;
; CR -> CURSOR TO LEFT MARGIN OF CURRENT LINE.
; BS -> CURSOR LEFT 1 CHARACTER UNLESS AT LEFT
;         MARGIN.
; LF -> CURSOR DOWN 1 LINE. IF AT BOTTOM OF SCREEN
;         THEN SCROLL UP ONE LINE.

$LIST
ConCharOut PROC FAR

	PUSH	DS
	PUSH	BP
	CALL	GetMyWindowState
	MOV	DS,AX
	MOV	BP,SP

	CALL      CharWidth
	MOV       DS:wsCharWt, AX
	CALL      LineHeight
	MOV       DS:wsLineHt, AX

	CALL	EnterWindows

	CALL	INVCSR
	MOV	AX,[BP+8]		; PARAMETER
	CALL	ConChar
	CALL	INVCSR

	CALL	LeaveWindows

	POP	BP
	POP	DS
	RET	2

ConCharOut ENDP

$EJ

; PROCEDURE ConLineOut (VAR ch: BYTES; count WORD);

ConLineOut PROC FAR

	PUSH	DS
	PUSH	BP
	CALL	GetMyWindowState
	MOV	DS,AX
	MOV	BP,SP

	CALL      CharWidth
	MOV       DS:wsCharWt, AX
	CALL      LineHeight
	MOV       DS:wsLineHt, AX

	CALL	EnterWindows

	CALL	INVCSR
	MOV	AX,[BP+12]	; SEGMENT
	MOV	ES,AX
	MOV	DI,[BP+10]	; ADDRESS
	MOV	CX,[BP+8]		; COUNT
 JCXZ ConLineOutNothing

ConLoop:
	MOV	AL,ES:[DI]
	PUSH	ES
	PUSH	CX
	PUSH	DI
	CALL	ConChar
	POP	DI
	POP	CX
	POP	ES
	INC	DI
	LOOP	ConLoop

ConLineOutNothing:
	CALL	INVCSR

	CALL	LeaveWindows

	POP	BP
	POP	DS
	RET	6

ConLineOut ENDP

$EJ

; This is the internal routine used by ConCharOut and ConLineOut.
;   AL = char to output
;   DS = window state

ConChar	PROC	NEAR

	CALL	xClip
	JLE	xFits
	MOV	BX, DS:wsClipRectTopLeftX
	ADD	BX, XHOME
	MOV	DS:wsXLoc, BX
	MOV	BX,DS:wsLineHt
          ADD	DS:wsYLoc,BX
xFits:
	CALL	yClipTop
	JGE	yTopFits
	MOV	BX, DS:wsClipRectTopLeftY
	ADD	BX, YHOME
	MOV	DS:wsYLoc, BX
	JMP 	SHORT yFits
yTopFits:
	CALL	yClipBot
	JLE	yFits

;ClipRectExtent... is really bottom right

	MOV	BX,DS:wsClipRectExtentY
          SUB	BX,DS:wsLineHt
;	SUB	BX, 2
	MOV	DS:wsYLoc,BX
	PUSH	AX
	CALL	SCROLLUP
	POP	AX
yFits:

	CMP	AL,CR
	JNE	NOT_CR
	JMP	IS_CR
NOT_CR:
	CMP	AL,BS
	JNE	NOT_BS
	JMP	IS_BS
NOT_BS:
	CMP	AL,LF
	JNE	NOT_LF
	JMP	IS_LF
NOT_LF:
	CMP	AL,ellipse
	JNE	NOT_Ellipse
	MOV	AL,ellipseCh
NOT_Ellipse:
	CMP	AL,shiftRet
	JNE	NOT_ShiftRet
	MOV	AL,shiftRetCh
$EJ


; ((bytesPerRow * lineHeight) * char ) + overhead

NOT_ShiftRet:
	XOR	AH,AH
	PUSH	AX
	LES	BX,DS:wsPFontTable
	MOV	AL, BYTE PTR ES:[BX+1] ; width
	MOV	CX,AX
	SHR	CX,1
	SHR	CX,1
	SHR	CX,1
	AND	AX,MOD8
	JZ	conMOD8
	INC	CX	; bytes per row
conMOD8:
	POP	AX
	CMP	CX,1
	JE	Skip1
	IMUL	CX	; char * bytesPerRow => first row
Skip1:
	ADD	AX,BX     ; add fontTable offset
	ADD	AX,fontOverhead
	PUSH	ES
	PUSH	AX
	MOV	AL, BYTE PTR ES:[BX] ; chars in fonttable
	XOR	AH,AH
 CMP AL,0
 JNE Not256
 MOV AH,1
Not256:
	CMP	CX,1
	JE	Skip2
	IMUL	CX	; bytesPerRow * entryCount = offset to next row
Skip2:
	PUSH	AX
	XOR	AH,AH
	MOV	AL, BYTE PTR ES:[BX+1]
	PUSH	AX
	MOV	AL, BYTE PTR ES:[BX+2]
	PUSH	AX

	PUSH      DS:wsPWindowSeg   ; screen location
	PUSH      DS:wsBytesPerLine   ; window size
	PUSH      DS:wsWindowHeight   ; window size

	MOV	AX,DS:wsXLoc
	ADD	AX,DS:wsTheWindowTopLeftX
	PUSH	AX
	MOV	AX,DS:wsYLoc
	ADD	AX,DS:wsTheWindowTopLeftY
	PUSH	AX

	CALL	BlitRectangle

	MOV	BX,DS:wsCharWt
	ADD	DS:wsXLoc,BX
	CALL	xClip
	JLE	nextFits
	MOV	BX, DS:wsClipRectTopLeftX
	ADD	BX, XHOME
	MOV	DS:wsXLoc, BX
	JMP	IS_LF
nextFits:
	RET

$EJ

IS_BS:

; CANNOT BACKSPACE PAST LEFT MARGIN.

	MOV	BX, DS:wsClipRectTopLeftX
	ADD	BX, XHOME
	CMP	DS:wsXLoc, BX
	JLE	noBS
	MOV	BX,DS:wsCharWt
	SUB	DS:wsXLoc,BX
noBS:
	RET

IS_CR:	MOV	BX, DS:wsClipRectTopLeftX
	ADD	BX, XHOME
	MOV	DS:wsXLoc, BX
	RET

IS_LF:
	MOV	BX,DS:wsLineHt
;	ADD	BX,2
	ADD	DS:wsYLoc,BX
	CALL	yClipBot
	JLE	NOSCROLL
	MOV	BX,DS:wsLineHt
;	ADD	BX,2
	SUB	DS:wsYLoc,BX
          CALL	ScrollUp
NOSCROLL:
	RET

ConChar	ENDP

$EJ

; Scroll window up by one line height and blank bottom line
; updateWindow is an output parameter only to Scroll.

updateWindow EQU [BP-8]

ScrollUp	PROC	NEAR

	PUSH	BP
	MOV	BP, SP
;	SUB	SP, 8

	MOV	AX, DS:wsClipRectExtentY
	SUB	AX, DS:wsClipRectTopLeftY
	INC	AX
	PUSH 	AX
	MOV	AX, DS:wsClipRectExtentX
	SUB	AX, DS:wsClipRectTopLeftX
	INC	AX
	PUSH 	AX
	PUSH	DS:wsClipRectTopLeftY
	PUSH 	DS:wsClipRectTopLeftX

	PUSH	SS
	LEA	AX, updateWindow
	PUSH	AX
	MOV	AX,up
	PUSH	AX
	MOV	AX,DS:wsLineHt
;	ADD	AX,2
	PUSH	AX
	CALL	WinScrollRectangle

	MOV	AX, DS:wsClipRectExtentY
	SUB	AX, DS:wsYLoc
	INC	AX
	MOV	SS:[BP-2], AX	; Extent Y

	MOV	AX, DS:wsYLoc
	MOV	SS:[BP-6], AX	; TopLeft y

	PUSH	SS
	LEA	AX, updateWindow
	PUSH	AX
	CALL	WinEraseRectangle

	MOV	SP, BP
	POP	BP
	RET

ScrollUp	ENDP

; Check if char will fit in window in the x dimension

xClip	PROC	NEAR
	MOV	BX, DS:wsClipRectTopLeftX
	INC	BX
	CMP	BX, DS:wsXLoc
	JG	EndxClip
	MOV	BX, DS:wsClipRectExtentX	; bottom right x
	SUB	BX,DS:wsCharWt
	CMP	DS:wsXLoc,BX
EndxClip:
	RET
xClip	ENDP
; Check if char will fit in window in the y dimension top

yClipTop	PROC	NEAR
	MOV	BX, DS:wsClipRectTopLeftY
	CMP	DS:wsYLoc, BX
	RET
yClipTop	ENDP

; Check if char will fit in window in the y dimension bottom

yClipBot	PROC	NEAR
	MOV	BX, DS:wsClipRectExtentY	; bottom right y
;	DEC	BX            ; Add 1 for extent,  Sub 2 for line distance
	INC	BX            ; Add 1 for extent
	SUB	BX,DS:wsLineHt
	CMP	DS:wsYLoc,BX
	RET
yClipBot	ENDP

$NOLIST
$EJ

; THIS ROUTINE INVERTS THE CURSOR AT THE  
; SPECIFIED X-Y COORDINATE IF THE CURSOR IS
; ON. THE CURSOR IS AN UNDERBAR.
;
;    DS:wsXLoc    X POSITION
;    DS:wsYLoc    Y POSITION

INVCSR	PROC	NEAR

	CMP	DS:wsCState,csrOn
	JE	DoCsr
	RET
DoCsr:
	CALL      CharHeight

	MOV	BX,DS:wsXLoc
	MOV	DX,DS:wsYLoc
	ADD	DX,AX	    ; YLoc + CharHeight
;	ADD	DX,DS:wsLineHt

	PUSH	BX
	PUSH	DX
	ADD	BX,DS:wsCharWt
	SUB	BX,2
	PUSH	BX
	PUSH	DX
	CALL	WinInvertLine	
	RET

INVCSR	ENDP

OS_CODE	ENDS

END
