$NOLIST DEBUG

NAME  NewWindowProcs

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

RAM_CGROUP GROUP RAM_CODE

PUBLIC WinSetAlternateWindow, WinCopyRemoteRectangle


EXTRN CpCopyRectangle:NEAR
EXTRN WinResetClip: FAR
EXTRN GetWindowState: NEAR

$EJECT
RAM_CODE SEGMENT  PUBLIC 'CODE'
	ASSUME CS:RAM_CGROUP
   ;General constants
  NULLWORD   EQU       0ffffh;
$LIST

;***************************************************************
;*						          *
;* PROCEDURE WinSetAlternateWindow (pAltWindow: PTR);          *
;*						          *
;***************************************************************

; Params and Locals


params  STRUC
;--------------
  oldBP	DW ?	; stack stuff
  oldDS	DW ?
  longReturn DD ?
;--------------
  alt_offset  DW ?	; param VAR ch: Char
  alt_segment DW ? 
params  ENDS

windowRegion  STRUC
  wrFormat     DB ?
  wrWidth      DW ?
  wrHeight     DW ?
  wrBufLength  DW ?
  wrPBufOff    DW ?
  wrPBufSeg    DW ?
  wrBitsPerPel DB ?
  wrBytesPerLn DW ?
windowRegion  ENDS

loc	EQU	[BP]
paramBytes   EQU       4

$LIST
WinSetAlternateWindow  PROC  FAR
   PUSH      BP
	MOV       BP, SP
   LES       DI, DWORD PTR [BP+6]            ; loc.alt_Offset
	POP       BP
	MOV       AX, ES
	CMP       AX, nullWord
	JE        validFormat
	CMP       ES:[DI].wrFormat, 1
	JNZ       validFormat
	RET	paramBytes

BackDoorSetAltWindow LABEL FAR
validFormat:
	PUSH	DS
	PUSH	BP
	CALL	GetWindowState
	MOV	DS, AX
	MOV	BP, SP         ; BP is now loc

	XOR       CL, CL	          ; onscreen = FALSE
	MOV       AX, DS:wsPScreenSeg	; IF windowState.pWindow =
	CMP       AX, DS:wsPWindowSeg	;    windowState.pScreen THEN
	JNE       TestGoToScreen
   MOV       CL, 1	          ; onscreen = TRUE

TestGoToScreen:
   LES       DI, DWORD PTR loc.alt_Offset
	MOV       AX, ES                ; If SELECTOROF (pAltWindow) =
	CMP       AX, nullWord	  ;    NULLWORD THEN
	JE        ToScreen
	JMP       NotToScreen

ToScreen:
   RCR       CL, 1               ; If onscreen THEN
	JNC       ContToScreen	;   RETURN;
	JMP       WinSetAltEnd

ContToScreen:
	LEA       DI, DS:wsTheWindowTopLeftX
	MOV       CX, 4
	MOV       AX, DS
	MOV       ES, AX
	LEA       SI, DS:wsScreenTopLeftX
	CLD
	REP       MOVSW               ; restore screen info

	MOV       AX, DS:wsPScreenSeg
	MOV       DS:wsPWindowSeg, AX
	XOR       AX, AX
	MOV       DS:wsPWindowOff, AX	; windowState.pWindow = windowState.pScreen
	MOV       AX, DS:wsScreenHeight
	MOV       DS:wsWindowHeight, AX  ; set window height

	XOR       AH, AH
	MOV       AL, DS:wsScreenBytesPerLine
	MOV       DS:wsBytesPerLine, AX  ; set bytes per line
	JMP       ResetTheWindow

NotToScreen:			;ELSE /* Not on screen */
   RCR       CL, 1               ; If onscreen THEN
	JNC       SetupWindowState	;   save screen info

	LEA       SI, DS:wsTheWindowTopLeftX
	MOV       CX, 4
	MOV       AX, DS
	MOV       ES, AX
	LEA       DI, DS:wsScreenTopLeftX
	CLD
	REP       MOVSW               ; save screen info

SetUpWindowState:
	XOR       AX, AX
	MOV       DS:wsTheWindowTopLeftX, AX
	MOV       DS:wsTheWindowTopLeftY, AX
   LES       DI, DWORD PTR loc.alt_Offset
	MOV       AX, ES:[DI].wrWidth
	MOV       DS:wsTheWindowExtentX, AX
	MOV       AX, ES:[DI].wrHeight
	MOV       DS:wsTheWindowExtentY, AX

	MOV       AX, ES:[DI].wrPBufOff
	MOV       DS:wsPWindowOff, AX
	MOV       AX, ES:[DI].wrPBufSeg
	MOV       DS:wsPWindowSeg, AX
	MOV       AX, ES:[DI].wrBytesPerLn
	MOV       DS:wsBytesPerLine, AX
	MOV       AX, ES:[DI].wrHeight
	MOV       DS:wsWindowHeight, AX

ResetTheWindow:
   CALL      WinResetClip

WinSetAltEnd:
	POP	BP
	POP	DS
	RET	paramBytes
WinSetAlternateWindow  ENDP
$NOLIST
PURGE        paramBytes
PURGE	params
PURGE	loc
PURGE	oldBP
PURGE	oldDS
PURGE	longReturn
PURGE        alt_offset
PURGE        alt_segment
PURGE        windowRegion
PURGE        wrFormat
PURGE        wrWidth
PURGE        wrHeight
PURGE        wrBufLength
PURGE        wrPBufOff
PURGE        wrPBufSeg
PURGE        wrBitsPerPel
PURGE        wrBytesPerLn
$EJ
$LIST
;**************************************************
;*					       *
;* PROCEDURE WinCopyRemoteRectangle 	       *
;*             (source: WindowRegionPtr;          *
;*              dest: WindowRegionPtr;            *
;*          VAR r: Rectangle;	                 *
;*		   newTopLeft: Point;                *
;*              mode: BYTE;                       *
;*					       *
;**************************************************
params STRUC
  r2_tpl_x	DW ?	; local r2: Rectangle
  r2_tpl_y	DW ?
  r2_ext_x	DW ?
  r2_ext_y	DW ?
  destTopLeftX DW ?
  destTopLeftY DW ?
  dest_bpl   DW ?
  dest_wh   DW ?
  destFormat   DW ?
  pDestSeg   DW ?
  sourceTopLeftX DW ?
  sourceTopLeftY DW ?
  source_bpl DW ?
  source_wh DW ?
  sourceFormat DW ?
  pSourceSeg DW ?
  r1_tpl_x	DW ?	; local r1: Rectangle
  r1_tpl_y	DW ?
  r1_ext_x	DW ?
  r1_ext_y	DW ?
  s_topLeftX DW ?
  s_topLeftY DW ?
  s_extentX  DW ?
  s_extentY  DW ?
  s_pWindowOff DW ?
  s_pWindowSeg DW ?
  s_bytesPerLn DW ?
  s_winHeight  DW ?
;--------------
  oldBP	DW ?	; stack stuff
  oldDS	DW ?
  longReturn	DD ?
;--------------
  mode       DW ?	; param mode: BYTE
  ntl_x	DW ?	; param newTopLeft: Point
  ntl_y	DW ?
  r_offset	DW ?	; param VAR r: Rectangle
  r_segment	DW ?
  destOff    DW ?	; param dest: WindowRegionPtr
  destSeg    DW ?
  sourceOff  DW ?	; param source: WindowRegionPtr
  sourceSeg  DW ?
params ENDS

windowRegion  STRUC
  wrFormat     DB ?
  wrWidth      DW ?
  wrHeight     DW ?
  wrBufLength  DW ?
  wrPBufOff    DW ?
  wrPBufSeg    DW ?
  wrBitsPerPel DB ?
  wrBytesPerLn DW ?
windowRegion  ENDS

loc	EQU	[BP]
localBytes	EQU	56
localBytestoR2 EQU	48
paramBytes   EQU       18
$LIST
WinCopyRemoteRectangle  PROC  FAR
	PUSH	DS
	PUSH	BP
	MOV	BP, SP			
	SUB	BP, localBytes		; [BP] is now loc
	SUB	SP, localBytesToR2 		; SP now is at r2

	CALL	GetWindowState
	MOV	DS, AX		; restore data seg
  ;save the window state
   MOV       AX, SS
	MOV       ES, AX
	LEA	SI, DS:wsTheWindowTopLeftX
	LEA	DI, loc.s_topLeftX
	MOV	CX, 8H		; rect size
	CLD
	REP MOVSB
	LES       DI, DWORD PTR DS:wsPWindowOff
	MOV       loc.s_PWindowOff, DI
	MOV       loc.s_PWindowSeg, ES
	MOV       AX, DS:wsBytesPerline
	MOV       loc.s_BytesPerLn, AX
	MOV       AX, DS:wsWindowHeight
	MOV       loc.s_WinHeight, AX

  ; set alternate window to source
	LES       DI, DWORD PTR loc.sourceOff
	MOV       AX, ES
	CMP       AX, NULLWORD
	JE        crGotScreenAsSource
	XOR       AH, AH
	MOV       AL, ES:[DI].wrFormat
	JMP       crSetSource
crGotScreenAsSource:
   XOR       AX, AX
crSetSource:
	MOV       loc.sourceFormat, AX
	PUSH      ES
	PUSH      DI
	CALL      BackDoorSetAltWindow

  ; save the source pointer and bytes per line
   MOV       AX, DS:wsBytesPerLine
	MOV       loc.source_bpl, AX
   MOV       AX, DS:wsWindowHeight
	MOV       loc.source_wh, AX
   LES       DI, DWORD PTR DS:wsPWindowOff
	MOV       loc.pSourceSeg, ES
	MOV       AX, DS:wsTheWindowTopLeftX
	MOV       loc.sourceTopLeftX, AX
	MOV       AX, DS:wsTheWindowTopLeftY
	MOV       loc.sourceTopLeftY, AX
  ; move the VAR parameter to a local on the stack
	PUSH	SS
	POP	ES
	LEA	DI, loc.r1_tpl_x
	MOV	CX, 8H		; rect size

	PUSH	SS	; ClipRectangleParm
   PUSH      DI
   PUSH      DS
	LDS	SI, DWORD PTR loc.r_Offset ; rect
	CLD
	REP MOVSB
	POP       DS

  ; clip the local rect
	CALL	ClipRectangle

  ; set window to dest
	LES       DI, DWORD PTR loc.destOff
	MOV       AX, ES
	CMP       AX, NULLWORD
	JE        crGotScreenAsDest
	XOR       AH, AH
	MOV       AL, BYTE PTR ES:[DI].wrFormat
	JMP       crSetDest
crGotScreenAsDest:
   XOR       AX, AX
crSetDest:
	MOV       loc.destFormat, AX
	PUSH      ES
	PUSH      DI
	CALL      BackDoorSetAltWindow

  ; save the dest pointer and bytes per line
   MOV       AX, DS:wsBytesPerLine
	MOV       loc.dest_bpl, AX
   MOV       AX, DS:wsWindowHeight
	MOV       loc.dest_wh, AX
   LES       DI, DWORD PTR DS:wsPWindowOff
	MOV       loc.pDestSeg, ES
	MOV       AX, DS:wsTheWindowTopLeftX
	MOV       loc.destTopLeftX, AX
	MOV       AX, DS:wsTheWindowTopLeftY
	MOV       loc.destTopLeftY, AX

  ; push another rect onto stack
	PUSH	loc.r1_ext_y	; -> r2.extent.y
	PUSH	loc.r1_ext_x	; r2.extent.x

  ; calculate the dest new top left
   LES       DI, DWORD PTR loc.r_Offset
	MOV       AX, loc.r1_tpl_x
	SUB       AX, ES:[DI].rectTopLeftX
	ADD       loc.ntl_x, AX

	MOV       AX, loc.r1_tpl_y
	SUB       AX, ES:[DI].rectTopLeftY
	ADD       loc.ntl_y, AX

	PUSH	loc.ntl_y
	PUSH	loc.ntl_x
	PUSH	SS		; address of r2
	PUSH	BP
	CALL	ClipRectangle  ; Clip(r2)
  ; test for r2.topLeft.y being clipped
	MOV	AX, loc.r2_tpl_y
	SUB	AX, loc.ntl_y
	JE	RcheckXClipping
  ; re-adjust r1.topLeft.y
	ADD	loc.r1_tpl_y, AX
RcheckXClipping:
  ; test for r2.topLeft.x being clipped
	MOV	AX, loc.r2_tpl_x
	SUB	AX, loc.ntl_x
	JE	RendClipping
  ; re-adjust r1.topLeft.x
	ADD	loc.r1_tpl_x, AX
RendClipping:
	MOV	CX, loc.r2_ext_x
	OR	CX, CX
	JLE	RnoCopy
	MOV	BX, loc.r2_ext_y
	OR	BX, BX
	JLE	RnoCopy
  ; copy the rectangles
   PUSH      loc.pSourceSeg     ; source selector
   PUSH      loc.source_bpl     ; bytes per line
   PUSH      loc.source_wh      ; window height
   PUSH      loc.sourceFormat     ; bytes per line

   PUSH      loc.pDestSeg       ; dest selector
   PUSH      loc.dest_bpl       ; dest bytes per line
   PUSH      loc.dest_wh        ; window height
   PUSH      loc.destFormat     ; bytes per line
	MOV	AX, loc.r1_tpl_x
	ADD	AX, loc.sourceTopLeftX
	PUSH	AX
	MOV	AX, loc.r1_tpl_y
	ADD	AX, loc.sourceTopLeftY
	PUSH	AX
	MOV	AX, loc.r2_tpl_x
	ADD	AX, loc.destTopLeftX
	PUSH	AX
	MOV	AX, loc.r2_tpl_y
	ADD	AX, loc.destTopLeftY
	PUSH	AX
	PUSH	CX	; r2.extent.x
	PUSH	BX	; r2.extent.y
	PUSH      loc.mode
	CALL	CpCopyRectangle

RnoCopy:
  ;restore the window state
	LEA	DI, DS:wsTheWindowTopLeftX
	LEA	SI, loc.s_topLeftX
   MOV       AX, DS
	MOV       ES, AX
   MOV       AX, SS
	MOV       DS, AX
	MOV	CX, 8H		; rect size
	CLD
	REP MOVSB

	LDS       DI, DWORD PTR loc.s_PWindowOff
	MOV       ES:wsPWindowOff, DI
	MOV       ES:wsPWindowSeg, DS
	MOV       AX, loc.s_BytesPerLn
	MOV       ES:wsBytesPerline, AX
	MOV       AX, loc.s_winHeight
	MOV       ES:wsWindowHeight, AX
	CALL      WinResetClip

  ; return clipped rectangle
	LES	DI, DWORD PTR loc.r_offset
	PUSH	SS
	POP	DS
	MOV	SI, BP	; DS:[SI] -> r2
	MOV	CX, 8H
	CLD
	REP MOVSB
	ADD	SP, localBytes	; remove r1, r2, etc
	POP	BP
	POP	DS
	RET	paramBytes
WinCopyRemoteRectangle  ENDP
$NOLIST
PURGE	params
PURGE	paramBytes
PURGE	loc
PURGE	localBytes
PURGE	r2_tpl_x
PURGE	r2_tpl_y
PURGE	r2_ext_x
PURGE	r2_ext_y
PURGE	r1_tpl_x
PURGE	r1_tpl_y
PURGE	r1_ext_x
PURGE	r1_ext_y
PURGE	oldBP
PURGE	oldDS
PURGE	longReturn
PURGE	ntl_x
PURGE	ntl_y
PURGE	r_offset
PURGE	r_segment
PURGE        destOff
PURGE        destSeg
PURGE        sourceOff
PURGE        sourceSeg
PURGE        s_extentY
PURGE        s_extentX
PURGE        s_topLeftY
PURGE        s_topLeftX
PURGE        s_pWindowOff
PURGE        s_pWindowSeg
PURGE        s_bytesPerLn
PURGE        s_winHeight
PURGE        dest_bpl
PURGE        dest_wh
PURGE        destFormat
PURGE        pDestSeg
PURGE        source_bpl
PURGE        source_wh
PURGE        sourceFormat
PURGE        pSourceSeg
PURGE        destTopLeftX
PURGE        destTopLeftY
PURGE        sourceTopLeftX
PURGE        sourceTopLeftY
PURGE        windowRegion
PURGE        wrFormat
PURGE        wrWidth
PURGE        wrHeight
PURGE        wrBufLength
PURGE        wrPBufOff
PURGE        wrPBufSeg
PURGE        wrBitsPerPel
PURGE        wrBytesPerLn
$EJECT

;**************************************************
;*					       *
;* PROCEDURE ClipRectangle(VAR r: Rect);	       *
;*					       *
;*  during loop: ES:[BP] = clip -Left or -Right   *
;*		  DS:[DI] = rect.topLeft.x or .y     *
;*					       *
;**************************************************
; This routine will clip a rectangle on window bounds
$LIST
ClipRectangle  PROC NEAR
   PUSH  	DS
	PUSH	BP
	CALL      GetWindowState
	MOV	ES, AX
	MOV	BP, SP
	LDS	DI, DWORD PTR [BP+6H]
	XOR	SI, SI
	LEA	BP, ES:wsTheWindowTopLeftX
clipRectLoop:
	MOV	CX, ES:[BP].rectExtentX
  ; clip the topleft if necessary
  ; 1st see if the rect.topLeft is negative
	MOV	BX, DS:[DI].rectTopLeftX
	OR        BX, BX
	JNS       CheckRightClipping
	ADD       DS:[DI].rectExtentX, BX  
	                              ; r.extentx := r.extentx - (0 - r.topLeftx)
	XOR       BX, BX
	MOV       DS:[DI].rectTopLeftX, BX         
	                              ; r.topleft.x := 0
	JMP       ClipXExtent
CheckRightClipping:
	CMP	BX, CX
	JL	clipXExtent
  ; truncate from the right
;	MOV       BX, CX
;	DEC       BX
;	MOV	DS:[DI].rectTopLeftX, BX
	XOR       AX, AX
	MOV       DS:[DI].rectExtentX, AX
	JMP SHORT xExtentOk

  ; clip the extent if necessary
clipXExtent:
;	MOV	BX, DS:[DI].rectTopLeftX
	ADD	BX, DS:[DI].rectExtentX
	CMP	BX, CX
	JLE	xExtentOK
  ; truncate from the right
	SUB       CX, DS:[DI].rectTopLeftX
	MOV	DS:[DI].rectExtentX, CX
  ; now test the vertical
xExtentOK:
	OR	SI, SI
	JNZ	clipRectEnd
	INC	SI
	INC	DI
	INC	DI
	INC	BP
	INC	BP
	JMP SHORT clipRectLoop
clipRectEnd:
	POP	BP
	POP       DS
	RET	4H
ClipRectangle ENDP
PURGE ClipRectLoop
PURGE ClipRectEnd
PURGE xExtentOk
PURGE clipXExtent

RAM_CODE ENDS

END
