; _______________________________________________________________________________________
;|                                                                                       |
;| ..::FreshLib::..  Free, open source. Licensed under "BSD 2-clause" license."          |
;|_______________________________________________________________________________________|
;
;  Description: Window management OS interface functions.
;
;  Target OS: Win32
;
;  Dependencies:
;
;  Notes:
;_________________________________________________________________________________________

iglobal
if used cWindowClassName
  cWindowClassName du 'FreshWin', 0
end if
endg

nWindowExtraBytes = 32
ofsWindowStruct = nWindowExtraBytes - 4

;_________________________________________________________________________________________
;
; Registers common window class
; Call only once
;_________________________________________________________________________________________

if used _CreateWindow
initialize __RegisterWindowClass

.wc WNDCLASS

begin
        xor     eax, eax
        lea     edi, [.wc]
        mov     ecx, sizeof.WNDCLASS / 4
        rep stosd

        mov     [.wc.style], CS_PARENTDC ; or CS_DBLCLKS or CS_VREDRAW or CS_HREDRAW
        mov     [.wc.lpfnWndProc], __CommonWindowProc
        mov     [.wc.cbWndExtra], nWindowExtraBytes

        mov     eax,[hInstance]
        mov     [.wc.hInstance],eax
        mov     [.wc.lpszClassName], cWindowClassName

        lea     eax, [.wc]
        invoke  RegisterClassW, eax

        return
endp
end if



;_________________________________________________________________________________________



body _CreateWindow

.pwc     dd ?
.charlen dd ?

.style dd ?
.exstyle dd ?

.rect RECT

begin
        pushad
        mov     esi, [.pWindow]

        mov     [.pwc], 0

        cmp     [esi+TWindow._caption], 0
        je      .caption_ok

        stdcall StrLen, [esi+TWindow._caption]
        lea     ecx, [eax*4]

        stdcall GetMem, ecx
        mov     [.pwc], eax

        stdcall StrPtr, [esi+TWindow._caption]

        invoke  MultiByteToWideChar, CP_UTF8, 0, eax, -1, [.pwc], ecx
        mov     [.charlen], eax

.caption_ok:

; now styles
        mov     eax, [esi+TWindow._border]
        and     eax, $3

        mov     ecx, [.styles+4*eax]
        mov     edx, [.exstyles+4*eax]

        mov     [.style], ecx
        mov     [.exstyle], edx

; the coordinates and size

        xor     eax, eax
        mov     [.rect.left], eax
        mov     [.rect.top],  eax
        mov     ecx, [esi+TWindow._width]
        mov     edx, [esi+TWindow._height]
        mov     [.rect.right], ecx
        mov     [.rect.bottom], edx

        lea     eax, [.rect]
        invoke  AdjustWindowRectEx, eax, [.style], 0, [.exstyle]

        mov     ecx, [.rect.right]
        mov     edx, [.rect.bottom]
        sub     ecx, [.rect.left]
        sub     edx, [.rect.top]

; the owner
        mov     eax, [esi+TWindow.__main]
        test    eax, eax
        jz      .owner_ok

        mov     eax, [eax+TWindow.handle]
.owner_ok:
        invoke  CreateWindowExW, [.exstyle], cWindowClassName, [.pwc], [.style], [esi+TWindow._x], [esi+TWindow._y], ecx, edx, eax, 0, [hInstance], 0
        mov     [esp+4*regEAX], eax

        invoke  SetWindowLongW, eax, ofsWindowStruct, esi

        stdcall FreeMem, [.pwc]

        popad
        return


.styles dd WS_POPUP or WS_VISIBLE
        dd WS_BORDER  or WS_CAPTION or WS_SYSMENU or WS_SIZEBOX or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or WS_VISIBLE
        dd WS_CAPTION or WS_SYSMENU or WS_VISIBLE
        dd WS_BORDER  or WS_CAPTION or WS_SYSMENU or WS_SIZEBOX or WS_VISIBLE

.exstyles dd WS_EX_TOPMOST or WS_EX_TOOLWINDOW or WS_EX_NOACTIVATE
          dd WS_EX_APPWINDOW
          dd WS_EX_DLGMODALFRAME
          dd WS_EX_TOOLWINDOW
endp



;_________________________________________________________________________________________



body _DestroyWindow
begin
        push    eax ecx edx
        invoke  DestroyWindow, [.hwnd]
        pop     edx ecx eax
        return
endp


;_________________________________________________________________________________________



body _ClientToScreen
begin
        push    eax

        lea     eax, [.x]

        invoke  ClientToScreen, [.hwnd], eax
        mov     ecx, [.x]
        mov     edx, [.y]
        pop     eax
        return
endp




;_________________________________________________________________________________________


body _ShowWindow
begin
        pushad

        mov     ebx, SW_HIDE
        cmp     [.flag], 0
        je      .com_ok

        mov     ebx, SW_SHOWNOACTIVATE

        invoke  GetWindowLongW, [.hwnd], GWL_STYLE
        test    eax, WS_POPUP
        jnz     .com_ok

        mov     ebx, SW_SHOWNORMAL

.com_ok:
        invoke  ShowWindow, [.hwnd], ebx

        popad
        return
endp


;_________________________________________________________________________________________


body _RefreshWindowRect
.rect RECT
begin
        push    eax ecx edx ebx

;; WAY 1 - direct paint on the window surface, without sending any messages.
;
;        invoke  GetDC, [.hwnd]
;        mov     ebx, eax
;
;        stdcall _GetWindowStruct, [.hwnd]
;        get     eax, eax, TWindow:ImgScreen
;
;        stdcall DrawImageRect, ebx, eax, [.x], [.y], [.x], [.y], [.width], [.height]
;
;        invoke  ReleaseDC, [.hwnd], ebx

; Needed for WAY2 and WAY3

        mov     eax, [.x]
        mov     ecx, [.y]
        mov     [.rect.left], eax
        mov     [.rect.top], ecx
        add     eax, [.width]
        add     ecx, [.height]
        mov     [.rect.right], eax
        mov     [.rect.bottom], ecx

        lea     eax, [.rect]
        xor     ecx, ecx

;; WAY2 - generates messages before returning.
;
        invoke  RedrawWindow, [.hwnd], eax, ecx, RDW_UPDATENOW or RDW_INVALIDATE or RDW_NOERASE

; WAY3 - returns immediately and posts messages to the queue.
; In the real Windows, on intensive changes it delays the update and that can be unwanted.
;
;        invoke  InvalidateRect, [.hwnd], eax, ecx

        pop     ebx edx ecx eax
        return
endp



;_________________________________________________________________________________________
;
; Returns the window TObject structure, from the window handle.
;_________________________________________________________________________________________

body _GetWindowStruct
begin
        push    ecx edx
        invoke  GetWindowLongW, [.hwin], ofsWindowStruct
        pop     edx ecx
        return
endp



;_________________________________________________________________________________________



body _SetWindowStruct
begin
        push    eax ecx edx
        invoke  SetWindowLongW, [.hwin], ofsWindowStruct, [.value]
        pop     edx ecx eax
        return
endp


;_________________________________________________________________________________________



body _SetWindowTextUtf8
.pwc dd ?
.charlen dd ?
begin
        push    eax ecx edx

        cmp     [.ptrUtf8], 0
        je      .finish

        stdcall StrLen, [.ptrUtf8]
        lea     ecx, [eax*4]

        stdcall GetMem, ecx
        mov     [.pwc], eax

        invoke  MultiByteToWideChar, CP_UTF8, 0, [.ptrUtf8], -1, [.pwc], ecx
        mov     [.charlen], eax

        invoke  SendMessageW, [.hwnd], WM_SETTEXT, 0, [.pwc]
        stdcall FreeMem, [.pwc]

.finish:
        pop     edx ecx eax
        return
endp



;_________________________________________________________________________________________


body _SetModalTowards
begin
        push    eax ecx edx

        invoke  SetWindowLongW, [.hwnd], GWL_HWNDPARENT, [.hwndParent]
        invoke  EnableWindow, [.hwndParent], FALSE

        pop     edx ecx eax
        return
endp


;_________________________________________________________________________________________


body _FinalizeModal
begin
        push    eax ecx edx
        invoke  EnableWindow, [.hwndParent], TRUE
        invoke  SetFocus, [.hwndParent]
        pop     edx ecx eax
        return
endp


;_________________________________________________________________________________________


proc __CommonWindowProc, .hwnd, .wmsg, .wparam, .lparam
begin
        stdcall __ProcessOneSystemEvent, [.hwnd], [.wmsg], [.wparam], [.lparam]         ; sometimes windows calls winproc directly instead of using postmessage.
        jnc     .finish

        invoke  DefWindowProcW, [.hwnd], [.wmsg], [.wparam], [.lparam]

.finish:
        return
endp

