
;--- implements:
;--- WriteConsoleOutputW
;--- ReadConsoleOutputW

        .386
if ?FLAT
        .MODEL FLAT, stdcall
else
        .MODEL SMALL, stdcall
endif

		option proc:private
        option casemap:none

        include winbase.inc
        include wincon.inc
        include dkrnl32.inc
        include macros.inc

?MOUSE		equ 1
?SETATTR	equ 0	;1=set text attribute in WriteConsoleOutputCharacter()
?BOXDRAWING	equ 1	;1=convert box drawing

          .CODE

;--- [in] lpBuffer: source buffer, ptr to CHAR_INFO items
;--- [in] dwBufferSize: size (X and Y) of source buffer
;--- [in] dwBufferCoord: upper left cell of source buffer to write data from
;--- [in/out] lpWriteRegion: destination rectangle in screen buffer

;--- the difference between A and W is just the "Char" field in CHAR_INFO
;--- so there is no need to convert it.

WriteConsoleOutputW proc public hConOut:dword,
		lpBuffer:ptr CHAR_INFO, dwBufferSize:COORD, dwBufferCoord:COORD,
        lpWriteRegion:ptr SMALL_RECT

if ?BOXDRAWING

local   offs:dword
local	dwCols:DWORD

		push	esi
        push	edi
        push	ebx
  if ?MOUSE
		invoke	KernelHideMouse
  endif
        invoke  getscreenptr, hConOut	;gets SCREENBUF in ecx
        mov     edi, eax
        mov		ebx, ecx
        mov     esi,lpWriteRegion
        movzx   ecx,[esi].SMALL_RECT.Left
        movzx   edx,[esi].SMALL_RECT.Top
        movzx   eax,[ebx].SCREENBUF.dwSize.X
        mul     edx
        add     eax,ecx
        shl     eax,1
        add     edi,eax					;edi=upper left corner in lpWriteRegion

        mov     esi, lpBuffer
		movzx	eax, dwBufferCoord.Y
        cmp		ax, dwBufferSize.Y
        jnc		done
        movzx   ecx, dwBufferSize.X
        mul		ecx
        movzx	ecx, dwBufferCoord.X
        cmp		cx, dwBufferSize.X
        jnc		done
        add		eax, ecx
        shl		eax, 2					;size of CHAR_INFO
        add		esi, eax				;esi = upper left corner in lpBuffer

		mov		edx, lpWriteRegion
		mov		cx, [edx].SMALL_RECT.Right
        sub		cx, [edx].SMALL_RECT.Left
        jc		done
        movzx	ecx,cx
        inc		ecx
        mov		dwCols, ecx

        movzx   eax, [ebx].SCREENBUF.dwSize.X
		movzx	ebx, dwBufferSize.X
        sub		ebx, ecx
        shl		ebx, 2					;* sizeof CHAR_INFO
        sub		eax, ecx
        shl		eax, 1
        mov		offs, eax
        
		mov		cx, [edx].SMALL_RECT.Bottom
        sub		cx, [edx].SMALL_RECT.Top
        jc		done
;        movzx	ecx,cx
        inc		ecx
  ife ?FLAT
		push	es
        push    @flat
        pop     es
  endif
nextrow:
        push    ecx
		mov		ecx, dwCols
nextcell:
		lodsd
		mov dl,al        
        shr eax,8
if ?BOXDRAWING
        cmp al,21h	;arrow drawing?
        jz arrowdraw
        cmp al,25h	;box drawing?
        jz boxdraw
boxcont:
endif        
		mov al,dl
        stosw
        loop    nextcell
        pop     ecx
        add     edi,offs
		add		esi,ebx
        loop    nextrow
  ife ?FLAT
        pop     es
  endif
done:
		@mov	eax,1
  if ?MOUSE
		invoke	KernelShowMouse
  endif
  ifdef _DEBUG
		mov ecx, lpWriteRegion
  endif

        pop 	ebx
        pop 	edi
		pop		esi
else
        invoke WriteConsoleOutputA, hConOut, lpBuffer, dwBufferSize, dwBufferCoord, lpWriteRegion
endif        
		@straceF DBGF_COUT, <"WriteConsoleOutputW(", hConOut, ", ", lpBuffer, ", ", dwBufferSize, ", ", dwBufferCoord, ", ", lpWriteRegion, " [", dword ptr [ecx].SMALL_RECT.Left, " ", dword ptr [ecx].SMALL_RECT.Right, "])=", eax>
        ret
if ?BOXDRAWING
arrowdraw:
        mov dh,''
        cmp dl,091h		;csr up
        jz @F
		mov dh,''
        cmp dl,093h		;csr down
        jz @F
        jmp boxcont
@@:
		mov dl,dh
        jmp boxcont
boxdraw:
        cmp dl,0D0h
        jnc boxcont
        movzx edx,dl
        cmp byte ptr [edx+boxchars],0
        jz boxcont
        mov dl,byte ptr [edx+boxchars]
        jmp boxcont
endif
		align 4
        
WriteConsoleOutputW endp

if ?BOXDRAWING
boxchars label byte
;--------- 0   1 2
		db 'Ä',0,'³',0,0,0,0,0,  0,0,0,0,'Ú',0,0,0 ;00-0F
		db '¿',0,0,0,'À',0,0,0,'Ù',0,0,0,'Ã',0,0,0 ;10-1F
		db 0,  0,0,0,'´',0,0,0,  0,0,0,0,'Â',0,0,0 ;20-2F
		db 0,  0,0,0,'Á',0,0,0,  0,0,0,0,'Å',0,0,0 ;30-3F
		db 0,  0,0,0, 0,0,0,0,0,0,0,0,     0,0,0,0 ;40-4F
		db 'Í','º',0,0,'É',0,0,'»',0,0,'È',0,'¼',0,0,0   ;50-5F
		db 'Ì',0,0,'¹',0,0,'Ë',0,0,'Ê',0,0,0,0,0,0 ;60-6F
		db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0         ;70-7F
		db 'ß',0,0,0,'Ü',0,0,0,'Û',0,0,0,'Ý',0,0,0 ;80-8F
		db 'Þ','°','±','²',0,0,0,0,0,0,0,0,0,0,0,0 ;90-9F
		db 'þ',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0       ;A0-AF
		db 0,0,'',0,0,0,'',0,0,0,'',0,'',0,0,0 ;B0-BF
		db '',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0       ;C0-CF
endif

ReadConsoleOutputW proc public hConOut:dword,
		pBuffer:ptr CHAR_INFO, dwBufferSize:COORD, dwBufferCoord:COORD,
        lpReadRegion:ptr SMALL_RECT

		invoke ReadConsoleOutputA, hConOut, pBuffer, dwBufferSize, dwBufferCoord, lpReadRegion
		@straceF DBGF_COUT,<"ReadConsoleOutputW(", hConOut, ", ", pBuffer, ", ", dwBufferSize, ", ", dwBufferCoord, ", ", lpReadRegion, ")=", eax>
        ret
		align 4
        
ReadConsoleOutputW endp
        
end

